On Wed, 2019-02-06 at 17:42 +0100, Michał Górny wrote: > Hi, > > I've been debugging a hanging test in LLDB. The particular test is > meant to verify that LLDB handles EOF on pty correctly. For this > purpose, it creates a pty and monitors it via kevent, then opens a slave > and closes it. Apparently, it expects kevent to report that master pty > has no longer any slaves open. > > I've tested this a bit and verified that read() from master pty returns > immediately if slave pty is closed. However, it seems that closing > the slave pty prevents kevent from reporting anything, therefore making > it wait forever. > And here's a proposed patch, based on kern/sys_pipe.c. I still have to write an ATF test for it. diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c index 1d60596124d3..0a235cc41aaa 100644 --- a/sys/kern/tty_pty.c +++ b/sys/kern/tty_pty.c @@ -920,40 +920,44 @@ filt_ptcread(struct knote *kn, long hint) if ((hint & NOTE_SUBMIT) == 0) { mutex_spin_enter(&tty_lock); } canread = (ISSET(tp->t_state, TS_ISOPEN) && ((tp->t_outq.c_cc > 0 && !ISSET(tp->t_state, TS_TTSTOP)) || ((pti->pt_flags & PF_PKT) && pti->pt_send) || ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl))); if (canread) { /* * c_cc is number of characters after output post-processing; * the amount of data actually read(2) depends on * setting of input flags for the terminal. */ kn->kn_data = tp->t_outq.c_cc; if (((pti->pt_flags & PF_PKT) && pti->pt_send) || ((pti->pt_flags & PF_UCNTL) && pti->pt_ucntl)) kn->kn_data++; + } else if (!ISSET(tp->t_state, TS_ISOPEN) && + !ISSET(tp->t_state, TS_CARR_ON)) { + kn->kn_flags |= EV_EOF; + canread = 1; } if ((hint & NOTE_SUBMIT) == 0) { mutex_spin_exit(&tty_lock); } return canread; } static void filt_ptcwdetach(struct knote *kn) { struct pt_softc *pti; pti = kn->kn_hook; mutex_spin_enter(&tty_lock); SLIST_REMOVE(&pti->pt_selw.sel_klist, kn, knote, kn_selnext); mutex_spin_exit(&tty_lock); } -- Best regards, Michał Górny
Attachment:
signature.asc
Description: This is a digitally signed message part