tty: Notify disconnections properly, and with B_SELECT_DISCONNECTED.

The tty_notify_select_event() at the end of tty_close_cookie()
checked if the other_tty's open_count was > 0 before notifying.
But in the case where the master is closing all children,
it will drop to 0 and leave things still in the select pool.
So we should notify unconditionally here.

Additionally, use B_SELECT_DISCONNECTED (i.e. POLLHUP). This matches
what Linux seems to do.

Fixes #19714.
This commit is contained in:
Augustin Cavalier
2025-09-03 18:37:47 -04:00
parent 5da70510b3
commit f7c3fa972c
+12 -11
View File
@@ -1528,11 +1528,8 @@ tty_close_cookie(tty_cookie* cookie)
requestLocker.Unlock();
// notify a select read and write event on the other tty, if we've closed this tty
if (cookie->other_tty->open_count > 0) {
tty_notify_select_event(cookie->other_tty, B_SELECT_WRITE);
tty_notify_select_event(cookie->other_tty, B_SELECT_READ);
}
// notify a select event on the other tty, if we've closed this tty
tty_notify_select_event(cookie->other_tty, B_SELECT_DISCONNECTED);
cookie->tty->is_exclusive = false;
}
@@ -1998,7 +1995,7 @@ tty_select(tty_cookie* cookie, uint8 event, uint32 ref, selectsync* sync)
"%p)\n", cookie, event, ref, sync));
// we don't support all kinds of events
if (event < B_SELECT_READ || event > B_SELECT_ERROR)
if (event < B_SELECT_READ || (event > B_SELECT_ERROR && event != B_SELECT_DISCONNECTED))
return B_BAD_VALUE;
// if the TTY is already closed, we notify immediately
@@ -2006,7 +2003,8 @@ tty_select(tty_cookie* cookie, uint8 event, uint32 ref, selectsync* sync)
if (!ttyReference.IsLocked()) {
TRACE(("tty_select() done: cookie %p already closed\n", cookie));
notify_select_event(sync, event);
if (event == B_SELECT_DISCONNECTED)
notify_select_event(sync, event);
return B_OK;
}
@@ -2042,10 +2040,8 @@ tty_select(tty_cookie* cookie, uint8 event, uint32 ref, selectsync* sync)
case B_SELECT_WRITE:
{
// writes go to the other TTY
if (!otherTTY) {
notify_select_event(sync, event);
if (otherTTY == NULL)
break;
}
// In case input is echoed, we have to check, whether we can
// currently can write to our TTY as well.
@@ -2063,6 +2059,11 @@ tty_select(tty_cookie* cookie, uint8 event, uint32 ref, selectsync* sync)
break;
}
case B_SELECT_DISCONNECTED:
if (otherTTY == NULL)
notify_select_event(sync, event);
break;
case B_SELECT_ERROR:
default:
break;
@@ -2081,7 +2082,7 @@ tty_deselect(tty_cookie* cookie, uint8 event, selectsync* sync)
sync));
// we don't support all kinds of events
if (event < B_SELECT_READ || event > B_SELECT_ERROR)
if (event < B_SELECT_READ || (event > B_SELECT_ERROR && event != B_SELECT_DISCONNECTED))
return B_BAD_VALUE;
// lock the TTY (guards the select sync pool, among other things)