From e2506c0bab8bb6d6d5bb286890d41fb6d80ee4b3 Mon Sep 17 00:00:00 2001 From: Matheus Date: Thu, 28 May 2026 14:15:35 -0300 Subject: [PATCH] pty: support POLLHUP --- kernel-src/include/kernel/tty.h | 3 +++ kernel-src/io/pty.c | 24 ++++++++++++++++-------- kernel-src/io/tty.c | 19 +++++++++++++++++++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/kernel-src/include/kernel/tty.h b/kernel-src/include/kernel/tty.h index 6e4ae649..49b5e10d 100644 --- a/kernel-src/include/kernel/tty.h +++ b/kernel-src/include/kernel/tty.h @@ -34,6 +34,8 @@ typedef struct { vnode_t *mastervnode; spinlock_t sessionlock; struct proc_t *session; + size_t opened; + bool has_been_opened; } tty_t; void tty_init(); @@ -41,5 +43,6 @@ tty_t *tty_create(char *name, ttydevicewritefn_t writefn, ttyinactivefn_t inacti void tty_process(tty_t *tty, char c); void tty_unregister(tty_t *tty); int tty_ioctl(tty_t *tty, unsigned long req, void *arg, int *result, cred_t *cred); +size_t tty_opened(tty_t *tty); #endif diff --git a/kernel-src/io/pty.c b/kernel-src/io/pty.c index 6800f5f3..a1590aa4 100644 --- a/kernel-src/io/pty.c +++ b/kernel-src/io/pty.c @@ -87,12 +87,6 @@ static int hup_check(void *_pty) { return pty->hangup; } -static void inactivepty(void *_pty) { - pty_t *pty = _pty; - freeptyminor(pty->minor); - freepty(pty); -} - static int isatty(int minor) { return 0; } @@ -119,9 +113,13 @@ static int close(int minor, int flags) { return 0; } +// TODO: also signal POLLHUP on tty close static int internalpoll(pty_t *pty, polldata_t *data, int events) { int revents = 0; + if (pty->tty->has_been_opened && tty_opened(pty->tty) == 0) + revents |= POLLHUP; + if (events & POLLOUT) revents |= POLLOUT; @@ -230,6 +228,15 @@ static int write(int minor, iovec_iterator_t *iovec_iterator, size_t size, uintm return 0; } +static void inactive(int minor) { + pty_t *pty = ptyget(minor); + if (pty == NULL) + return; + + freeptyminor(pty->minor); + freepty(pty); +} + static devops_t devops = { .open = open, .isatty = isatty, @@ -237,7 +244,8 @@ static devops_t devops = { .close = close, .poll = poll, .read = read, - .ioctl = ioctl + .ioctl = ioctl, + .inactive = inactive }; static int open(int oldminor, vnode_t **vnode, int flags) { @@ -276,7 +284,7 @@ static int open(int oldminor, vnode_t **vnode, int flags) { // create a pairing slave device snprintf(tmpname, 20, "pts/%d", newminor); - pty->tty = tty_create(tmpname, writetopty, inactivepty, NULL, hup_check, pty); + pty->tty = tty_create(tmpname, writetopty, NULL, NULL, hup_check, pty); if (pty->tty == NULL) { VOP_RELEASE(pty->mastervnode); return ENOMEM; diff --git a/kernel-src/io/tty.c b/kernel-src/io/tty.c index a15a8597..092e9949 100644 --- a/kernel-src/io/tty.c +++ b/kernel-src/io/tty.c @@ -426,7 +426,10 @@ static int open(int minor, vnode_t **vnode, int flags) { } VOP_RELEASE(*vnode); + __atomic_fetch_add(&ctty->opened, 1, __ATOMIC_SEQ_CST); + ctty->has_been_opened = true; *vnode = (vnode_t *)(ctty->mastervnode); + return 0; } else if (tty == NULL) { return ENODEV; } else if ((flags & V_FFLAGS_NOCTTY) == 0) { @@ -434,6 +437,18 @@ static int open(int minor, vnode_t **vnode, int flags) { jobctl_setctty(current_thread()->proc, tty, false); } + __atomic_fetch_add(&tty->opened, 1, __ATOMIC_SEQ_CST); + tty->has_been_opened = true; + return 0; +} + +static int close(int minor, int flags) { + tty_t *tty = ttyget(minor); + if (tty == NULL) + return ENODEV; + + int count = __atomic_fetch_sub(&tty->opened, 1, __ATOMIC_SEQ_CST); + __assert(count != 0); return 0; } @@ -484,6 +499,7 @@ static devops_t devops = { .ioctl = ioctl, .isatty = isatty, .open = open, + .close = close, .inactive = inactive }; @@ -574,6 +590,9 @@ void tty_unregister(tty_t *tty) { } } +size_t tty_opened(tty_t *tty) { + return __atomic_load_n(&tty->opened, __ATOMIC_SEQ_CST); +} void tty_init() { __assert(devfs_register(&devops, "tty", V_TYPE_CHDEV, DEV_MAJOR_TTY, CONTROLLING_TTY_MINOR, 0666, NULL) == 0);