From owner-p4-projects@FreeBSD.ORG Wed Aug 27 16:48:16 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7A4731065676; Wed, 27 Aug 2008 16:48:16 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 38BB3106568A for ; Wed, 27 Aug 2008 16:48:16 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 30EB28FC15 for ; Wed, 27 Aug 2008 16:48:16 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.2/8.14.2) with ESMTP id m7RGmGiV020295 for ; Wed, 27 Aug 2008 16:48:16 GMT (envelope-from ed@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.2/8.14.1/Submit) id m7RGmG5d020293 for perforce@freebsd.org; Wed, 27 Aug 2008 16:48:16 GMT (envelope-from ed@FreeBSD.org) Date: Wed, 27 Aug 2008 16:48:16 GMT Message-Id: <200808271648.m7RGmG5d020293@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to ed@FreeBSD.org using -f From: Ed Schouten To: Perforce Change Reviews Cc: Subject: PERFORCE change 148628 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 27 Aug 2008 16:48:16 -0000 http://perforce.freebsd.org/chv.cgi?CH=148628 Change 148628 by ed@ed_dull on 2008/08/27 16:48:04 Fix a deadlock in TTY's. Not a kernel deadlock, but a situation where a TTY could become useless. Because we now only have one contiguous input buffer, there is a way for us to fill up the input buffer without needing to go into the high watermark, namely when we are in canonical mode and type in as much data as possble. Change the TTY discipline code to only enter the high watermark when we can't store any more data *and* when we actually have data available for read(). This means we must also fix up rint_poll() to return something (1) when there isn't actually any place to make pts(4) consumers happy. Affected files ... .. //depot/projects/mpsafetty/sys/kern/tty_ttydisc.c#15 edit .. //depot/projects/mpsafetty/sys/sys/ttydisc.h#5 edit Differences ... ==== //depot/projects/mpsafetty/sys/kern/tty_ttydisc.c#15 (text+ko) ==== @@ -307,7 +307,6 @@ ttydisc_read(struct tty *tp, struct uio *uio, int ioflag) { int error; - size_t c; tty_lock_assert(tp, MA_OWNED); @@ -324,8 +323,8 @@ 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); } @@ -1003,7 +1002,20 @@ 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); } ==== //depot/projects/mpsafetty/sys/sys/ttydisc.h#5 (text+ko) ==== @@ -84,10 +84,21 @@ 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