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