sh: Improve error handling in read builtin:

* If read -t times out, return status as if interrupted by SIGALRM
  (formerly 1).
* If a trapped signal interrupts read, return status 128+sig (formerly 1).
* If [EINTR] occurs but there is no trap, retry the read (for example
  because of a SIGWINCH in interactive mode).
* If a read error occurs, write an error message and return status 2.

As before, a variable assignment error returns 2 and discards the remaining
data read.
This commit is contained in:
Jilles Tjoelker 2013-05-03 15:28:31 +00:00
parent 6c21893360
commit c4539460e3
4 changed files with 47 additions and 5 deletions

View File

@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include "error.h"
#include "mystring.h"
#include "syntax.h"
#include "trap.h"
#undef eflag
@ -102,6 +103,8 @@ readcmd(int argc __unused, char **argv __unused)
struct timeval tv;
char *tvptr;
fd_set ifds;
ssize_t nread;
int sig;
rflag = 0;
prompt = NULL;
@ -156,8 +159,10 @@ readcmd(int argc __unused, char **argv __unused)
/*
* If there's nothing ready, return an error.
*/
if (status <= 0)
return(1);
if (status <= 0) {
sig = pendingsig;
return (128 + (sig != 0 ? sig : SIGALRM));
}
}
status = 0;
@ -165,7 +170,19 @@ readcmd(int argc __unused, char **argv __unused)
backslash = 0;
STARTSTACKSTR(p);
for (;;) {
if (read(STDIN_FILENO, &c, 1) != 1) {
nread = read(STDIN_FILENO, &c, 1);
if (nread == -1) {
if (errno == EINTR) {
sig = pendingsig;
if (sig == 0)
continue;
status = 128 + sig;
break;
}
warning("read error: %s", strerror(errno));
status = 2;
break;
} else if (nread != 1) {
status = 1;
break;
}

View File

@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$
.\"
.Dd April 21, 2013
.Dd May 3, 2013
.Dt SH 1
.Os
.Sh NAME
@ -2372,7 +2372,9 @@ option is specified and the
elapses before a complete line of input is supplied,
the
.Ic read
command will return an exit status of 1 without assigning any values.
command will return an exit status as if terminated by
.Dv SIGALRM
without assigning any values.
The
.Ar timeout
value may optionally be followed by one of
@ -2388,6 +2390,11 @@ is assumed.
The
.Fl e
option exists only for backward compatibility with older scripts.
.Pp
The exit status is 0 on success, 1 on end of file,
between 2 and 128 if an error occurs
and greater than 128 if a trapped signal interrupts
.Ic read .
.It Ic readonly Oo Fl p Oc Op Ar name ...
Each specified
.Ar name

View File

@ -0,0 +1,5 @@
# $FreeBSD$
{ errmsg=`read x <&- 2>&1 >&3`; } 3>&1
r=$?
[ "$r" -ge 2 ] && [ "$r" -le 128 ] && [ -n "$errmsg" ]

View File

@ -0,0 +1,13 @@
# $FreeBSD$
T=`mktemp -d ${TMPDIR:-/tmp}/sh-test.XXXXXX`
trap 'rm -rf $T' 0
cd $T || exit 3
mkfifo fifo1
trapped=
trap trapped=1 QUIT
{ kill -QUIT $$; sleep 1; exit 4; } >fifo1 &
read dummy <fifo1
r=$?
kill $!
[ "$r" -gt 128 ] && [ -n "$trapped" ]