From owner-freebsd-bugs@FreeBSD.ORG Sat Jan 7 08:30:14 2012 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7AA7610656D5 for ; Sat, 7 Jan 2012 08:30:14 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 5D53E8FC1B for ; Sat, 7 Jan 2012 08:30:14 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.5/8.14.5) with ESMTP id q078UEsF064664 for ; Sat, 7 Jan 2012 08:30:14 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.5/8.14.5/Submit) id q078UEkB064661; Sat, 7 Jan 2012 08:30:14 GMT (envelope-from gnats) Date: Sat, 7 Jan 2012 08:30:14 GMT Message-Id: <201201070830.q078UEkB064661@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: Bruce Evans Cc: Subject: Re: misc/163871: 'script' save endline as ^M X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Bruce Evans List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 07 Jan 2012 08:30:14 -0000 The following reply was made to PR bin/163871; it has been noted by GNATS. From: Bruce Evans To: Bruce Evans Cc: Eugen Konkov , freebsd-gnats-submit@FreeBSD.org, freebsd-bugs@FreeBSD.org Subject: Re: misc/163871: 'script' save endline as ^M Date: Sat, 7 Jan 2012 19:24:15 +1100 (EST) On Sat, 7 Jan 2012, Bruce Evans wrote: > ... > watch(8) probably works better for input too. Someone recently tried to > fix EOF handling in script(1) and had problems using VEOF since this gives > input processing unless the default echo mode is turned off. Perhaps > watch(8) can handle this better too. But watch doesn't understand EOF at > all, and is hard to terminate (the old version that I'm testing with > is terminated by ^G which generates a SIGINT, but it dumps core instead > of catching this signal as intended, and all versions have an unsafe > SIGINT handler which asks for core dumps). The core dump is because watch(8) tries to shoot its foot off, but only I notice because only my tty driver has been fixed to do the shooting. watch(8) sets both VINTR and VQUIT to ^G. This should (*) result in ^G generating both a SIGINT and a SIGQUIT, and the SIGQUIT must terminate watch(8) since watch(8) only catches SIGINT. But the unfixed tty driver only generates SIGINT. The same bug affects VSUSP matching either VINTR or VSUSP, bu I didn't fix that. (*) POSIX doesn't seem to say what happens when control characters are equal, but it is hard to read its general specification of them as allowing the bugs. From POSIX.1-2001-draft7 (the 2007 draft is similar): % 6722 INTR Special character on input, which is recognized if the ISIG flag is set. Generates a % 6723 SIGINT signal which is sent to all processes in the foreground process group for which % 6724 the terminal is the controlling terminal. If ISIG is set, the INTR character shall be % 6725 discarded when processed. % 6726 QUIT Special character on input, which is recognized if the ISIG flag is set. Generates a % 6727 SIGQUIT signal which is sent to all processes in the foreground process group for % 6728 which the terminal is the controlling terminal. If ISIG is set, the QUIT character shall be % 6729 discarded when processed. % 6747 SUSP If the ISIG flag is set, receipt of the SUSP character shall cause a SIGTSTP signal to be % 6748 sent to all processes in the foreground process group for which the terminal is the % 6749 controlling terminal, and the SUSP character shall be discarded when processed. This says that these special characters are "recognized" and the corresponding signal is sent whenever ISIG is set. The characters are discarded after processing them. It takes a weaselish reading to allow the bug: we have to discard the characters after processing them just enough to generate a signal for them after processing them as another type of control character. But I believe the discarding wasn't meant to do that. It is just to keep these characters out of the final input. FreeBSD's termios(4) has essentially the same wording for this. % ... % 7019 If ISIG is set, each input character shall be checked against the special control characters INTR, % 7020 QUIT, and SUSP. If an input character matches one of these control characters, the function % 7021 associated with that character shall be performed. If ISIG is not set, no checking shall be done. This specifies what must be done if an input character matches "one" of the control characters. If it matches more than one, then it certainly matches just one, so this can be read as requiring the action to be performed for all matches. "one" can be read as "only one", but I think this is reading too much uniqueness into "one". And if "only one" is meant, the precedence becomes important, but nothing is said about precedence. Anyway, the behaviour when some V characters are identical is very unportable, so they should never be be identical, and applications should not make some identical by changing only some and accidentally matching others. watch(8) is setting VQUIT because it doesn't want to get SIGQUIT. It is only accidental that setting it to the same as VINTR normally avoids the SIGQUIT (because VINTR has precedence, and the bug prevents getting both signals). It should be setting VQUIT to _POSIX_VDISABLE to avoid SIGQUIT (it must do something, since the user might already have set it to ^G, in which case setting only VINTR to ^G would create the ambiguiuty). Before _POSIX_VDISABLE existed, the only way to kill a control characted was to set it to a harmless value. The null character may have been most harmless, and VQUIT = VINTR was apparently harmless too since most tty drivers had the bug. Maybe POSIX requires the bug somewhere, for historical incompatibility, although with _POSIX_VDISABLE it doesn't need this hack. VQUIT is set by remarkably few applications in /usr/src (especially to a hard-coded value), so watch(8) is the main example of this. Newer code tends to use _POSIX_VDISABLE. "stty sane" doesn't change control characters, so after watch(8) didn't restore the state, I saw much further weirdness from VINTR = VQUIT. Most applications catch neither signal, and so they get killed normally by SIGINT for ^G instead of ^C. Others tend to catch both SIGINT and ignore SIGQUIT, so they don't get killed like watch(8). Bruce