From a15ec0a5e499e02b84aa008de8947f227914b07c Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Fri, 29 Aug 2008 15:02:50 +0000 Subject: [PATCH] Backport two small fixes from the MPSAFE TTY branch in Perforce: - Implement IMAXBEL. It turned out the IMAXBEL termios switch was marked as supported, while it had not been implemented. - Don't go into the high watermark when in canonical mode, no data has been canonicalized and the input buffer is full. This caused the terminal to lock up. This prevented users from pressing backspace/^U/etc in such cases. This could easily be simulated by pasting a very big amount of data in a shell with sh(1) in canonical mode. Obtained from: //depot/projects/mpsafetty/... --- sys/kern/tty_ttydisc.c | 20 ++++++++++++++++---- sys/sys/ttydisc.h | 15 ++++++++++++--- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/sys/kern/tty_ttydisc.c b/sys/kern/tty_ttydisc.c index b52fc18b603b..6244166b9bed 100644 --- a/sys/kern/tty_ttydisc.c +++ b/sys/kern/tty_ttydisc.c @@ -305,7 +305,6 @@ int ttydisc_read(struct tty *tp, struct uio *uio, int ioflag) { int error; - size_t c; tty_lock_assert(tp, MA_OWNED); @@ -322,8 +321,8 @@ ttydisc_read(struct tty *tp, struct uio *uio, int ioflag) else error = ttydisc_read_raw_interbyte_timer(tp, uio, ioflag); - c = ttyinq_bytesleft(&tp->t_inq); - if (c >= tp->t_inlow) { + if (ttyinq_bytesleft(&tp->t_inq) >= tp->t_inlow || + ttyinq_bytescanonicalized(&tp->t_inq) == 0) { /* Unset the input watermark when we've got enough space. */ tty_hiwat_in_unblock(tp); } @@ -1001,7 +1000,20 @@ parmrk: print: /* See if we can store this on the input queue. */ if (ttyinq_write_nofrag(&tp->t_inq, ob, ol, quote) != 0) { - /* We cannot. Enable the input watermark. */ + if (CMP_FLAG(i, IMAXBEL)) + ttyoutq_write_nofrag(&tp->t_outq, "\a", 1); + + /* + * Prevent a deadlock here. It may be possible that a + * user has entered so much data, there is no data + * available to read(), but the buffers are full anyway. + * + * Only enter the high watermark if the device driver + * can actually transmit something. + */ + if (ttyinq_bytescanonicalized(&tp->t_inq) == 0) + return (0); + tty_hiwat_in_block(tp); return (-1); } diff --git a/sys/sys/ttydisc.h b/sys/sys/ttydisc.h index dd170e6cc4b1..0d43666ab8fb 100644 --- a/sys/sys/ttydisc.h +++ b/sys/sys/ttydisc.h @@ -84,10 +84,19 @@ ttydisc_write_poll(struct tty *tp) static __inline size_t ttydisc_rint_poll(struct tty *tp) { + size_t l; - tty_lock_assert(tp, MA_OWNED); - - return ttyinq_bytesleft(&tp->t_inq); + /* + * XXX: Still allow character input when there's no space in the + * buffers, but we haven't entered the high watermark. This is + * to allow backspace characters to be inserted when in + * canonical mode. + */ + l = ttyinq_bytesleft(&tp->t_inq); + if (l == 0 && (tp->t_flags & TF_HIWAT_IN) == 0) + return (1); + + return (l); } static __inline size_t