git: 2520c8bd2c42 - stable/15 - tty: do not recurse on ttydev_close()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 16 Aug 2026 02:46:22 UTC
The branch stable/15 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=2520c8bd2c42f4333bc1f4b94a78efa625bc97c9
commit 2520c8bd2c42f4333bc1f4b94a78efa625bc97c9
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-08-07 19:48:31 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
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. */