git: 2520c8bd2c42 - stable/15 - tty: do not recurse on ttydev_close()
Konstantin Belousov <[email protected]>
| Newsgroups | gmane.os.freebsd.devel.cvs.src,gmane.os.freebsd.devel.stable.scm |
|---|---|
| Message-ID | <[email protected]> |
The branch stable/15 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=2520c8bd2c42f4333bc1f4b94a78efa625bc97c9 commit 2520c8bd2c42f4333bc1f4b94a78efa625bc97c9 Author: Konstantin Belousov <[email protected]> AuthorDate: 2026-08-07 19:48:31 +0000 Commit: Konstantin Belousov <[email protected]> CommitDate: 2026-08-16 02:41:17 +0000 tty: do not recurse on ttydev_close() (cherry picked from commit e2cfbd498af88a211b0b347861cfd989e57cd1fb) --- sys/kern/tty.c | 30 +++++++++++++++++++++--------- sys/sys/tty.h | 1 + 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 5f6afa49b70d..09ed1c6d0c5d 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -71,7 +71,7 @@ static MALLOC_DEFINE(M_TTY, "tty", "tty device"); -static void tty_rel_free(struct tty *tp); +static void tty_rel_free(struct tty *tp, bool inttydevclose); static TAILQ_HEAD(, tty) tty_list = TAILQ_HEAD_INITIALIZER(tty_list); static struct sx tty_list_sx; @@ -229,13 +229,15 @@ ttydev_enter(struct tty *tp) } static void -ttydev_leave(struct tty *tp) +ttydev_leave(struct tty *tp, bool inttydevclose) { tty_assert_locked(tp); if (tty_opened(tp) || tp->t_flags & TF_OPENCLOSE) { /* Device is still opened somewhere. */ + if (inttydevclose) + tp->t_flags &= ~TF_INDEVCLOSE; tty_unlock(tp); return; } @@ -262,7 +264,7 @@ ttydev_leave(struct tty *tp) tp->t_flags &= ~TF_OPENCLOSE; cv_broadcast(&tp->t_dcdwait); - tty_rel_free(tp); + tty_rel_free(tp, inttydevclose); } /* @@ -363,7 +365,7 @@ ttydev_open(struct cdev *dev, int oflags, int devtype __unused, done: tp->t_flags &= ~TF_OPENCLOSE; cv_broadcast(&tp->t_dcdwait); - ttydev_leave(tp); + ttydev_leave(tp, false); return (error); } @@ -375,6 +377,11 @@ ttydev_close(struct cdev *dev, int fflag, int devtype __unused, struct tty *tp = dev->si_drv1; tty_lock(tp); + if ((tp->t_flags & TF_INDEVCLOSE) != 0) { + tty_unlock(tp); + return (0); + } + tp->t_flags |= TF_INDEVCLOSE; /* * Don't actually close the device if it is being used as the @@ -388,6 +395,7 @@ ttydev_close(struct cdev *dev, int fflag, int devtype __unused, tp->t_flags &= ~(TF_OPENED_IN|TF_OPENED_OUT); if (tp->t_flags & TF_OPENED) { + tp->t_flags &= ~TF_INDEVCLOSE; tty_unlock(tp); return (0); } @@ -407,7 +415,7 @@ ttydev_close(struct cdev *dev, int fflag, int devtype __unused, cv_broadcast(&tp->t_bgwait); cv_broadcast(&tp->t_dcdwait); - ttydev_leave(tp); + ttydev_leave(tp, true); return (0); } @@ -1144,7 +1152,7 @@ tty_dealloc(void *arg) } static void -tty_rel_free(struct tty *tp) +tty_rel_free(struct tty *tp, bool inttydevclose) { struct cdev *dev; @@ -1153,6 +1161,8 @@ tty_rel_free(struct tty *tp) #define TF_ACTIVITY (TF_GONE|TF_OPENED|TF_HOOK|TF_OPENCLOSE) if (tp->t_sessioncnt != 0 || (tp->t_flags & TF_ACTIVITY) != TF_GONE) { /* TTY is still in use. */ + if (inttydevclose) + tp->t_flags &= ~TF_INDEVCLOSE; tty_unlock(tp); return; } @@ -1163,6 +1173,8 @@ tty_rel_free(struct tty *tp) /* TTY can be deallocated. */ dev = tp->t_dev; tp->t_dev = NULL; + if (inttydevclose) + tp->t_flags &= ~TF_INDEVCLOSE; tty_unlock(tp); if (dev != NULL) { @@ -1199,7 +1211,7 @@ tty_rel_sess(struct tty *tp, struct session *sess) MPASS(tp->t_pgrp == NULL); } tp->t_sessioncnt--; - tty_rel_free(tp); + tty_rel_free(tp, false); } void @@ -1218,7 +1230,7 @@ tty_rel_gone(struct tty *tp) cv_broadcast(&tp->t_dcdwait); tp->t_flags |= TF_GONE; - tty_rel_free(tp); + tty_rel_free(tp, false); } static int @@ -2226,7 +2238,7 @@ ttyhook_unregister(struct tty *tp) ttydisc_optimize(tp); /* Maybe deallocate the TTY as well. */ - tty_rel_free(tp); + tty_rel_free(tp, false); } /* diff --git a/sys/sys/tty.h b/sys/sys/tty.h index f1b2646c942d..6a58908d97a4 100644 --- a/sys/sys/tty.h +++ b/sys/sys/tty.h @@ -87,6 +87,7 @@ struct tty { #define TF_BUSY_IN 0x20000 /* Process busy in read() -- not supported. */ #define TF_BUSY_OUT 0x40000 /* Process busy in write(). */ #define TF_BUSY (TF_BUSY_IN|TF_BUSY_OUT) +#define TF_INDEVCLOSE 0x80000 /* In ttydev_close() */ unsigned int t_revokecnt; /* (t) revoke() count. */ /* Buffering mechanisms. */