struct tty_dev_t *driver;
struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver);
struct tty *tp;
-
+
if (pti == NULL)
return (ENXIO);
save_timeout = tp->t_timeout;
tp->t_timeout = 60;
#endif
+ /*
+ * Close the line discipline and backing TTY structures.
+ */
err = (*linesw[tp->t_line].l_close)(tp, flag);
- ptsstop(tp, FREAD|FWRITE);
- (void) ttyclose(tp);
+ (void)ttyclose(tp);
+
+ /*
+ * Flush data and notify any waiters on the master side of this PTY.
+ */
+ ptsstop(tp, FREAD | FWRITE);
#ifdef FIX_VSX_HANG
tp->t_timeout = save_timeout;
#endif
struct tty_dev_t *driver;
struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver);
struct tty *tp;
+ struct knote *kn;
+
+ if (!pti) {
+ return ENXIO;
+ }
- if (pti == NULL)
- return (ENXIO);
tp = pti->pt_tty;
tty_lock(tp);
- (void)(*linesw[tp->t_line].l_modem)(tp, 0);
-
/*
- * XXX MDMBUF makes no sense for ptys but would inhibit the above
- * l_modem(). CLOCAL makes sense but isn't supported. Special
- * l_modem()s that ignore carrier drop make no sense for ptys but
- * may be in use because other parts of the line discipline make
- * sense for ptys. Recover by doing everything that a normal
- * ttymodem() would have done except for sending a SIGHUP.
+ * XXX MDMBUF makes no sense for PTYs, but would inhibit an `l_modem`.
+ * CLOCAL makes sense but isn't supported. Special `l_modem`s that ignore
+ * carrier drop make no sense for PTYs but may be in use because other parts
+ * of the line discipline make sense for PTYs. Recover by doing everything
+ * that a normal `ttymodem` would have done except for sending SIGHUP.
*/
+ (void)(*linesw[tp->t_line].l_modem)(tp, 0);
if (tp->t_state & TS_ISOPEN) {
tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED);
tp->t_state |= TS_ZOMBIE;
ttyflush(tp, FREAD | FWRITE);
}
- tp->t_oproc = 0; /* mark closed */
+ /*
+ * Null out the backing TTY struct's open procedure to prevent starting
+ * slaves through `ptsstart`.
+ */
+ tp->t_oproc = NULL;
+
+ /*
+ * Clear any select or kevent waiters under the lock.
+ */
+ SLIST_FOREACH(kn, &pti->pt_selr.si_note, kn_selnext) {
+ KNOTE_DETACH(&pti->pt_selr.si_note, kn);
+ }
+ selthreadclear(&pti->pt_selr);
+ SLIST_FOREACH(kn, &pti->pt_selw.si_note, kn_selnext) {
+ KNOTE_DETACH(&pti->pt_selw.si_note, kn);
+ }
+ selthreadclear(&pti->pt_selw);
tty_unlock(tp);