diff --git a/NEWS b/NEWS index 5097a7eea..3010c825d 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,9 @@ Any uppercase BUG_* names are modernish shell bug IDs. did not perform an assignment and yielded the value 0 if 'var' was typeset as numeric (integer or float) but had not yet been assigned a value. +- Fixed a bug introduced on 2020-08-19: Ctrl+D would break after an + interactive shell received SIGWINCH. + 2021-03-05: - Unbalanced quotes and backticks now correctly produce a syntax error diff --git a/src/cmd/ksh93/edit/edit.c b/src/cmd/ksh93/edit/edit.c index a890e56af..db00165b5 100644 --- a/src/cmd/ksh93/edit/edit.c +++ b/src/cmd/ksh93/edit/edit.c @@ -833,15 +833,14 @@ static void ed_nputchar(register Edit_t *ep, int n, int c) /* * Do read, restart on interrupt unless SH_SIGSET or SH_SIGTRAP is set - * Use sfpkrd() to poll() or select() to wait for input if possible + * Use select(2) (via sfpkrd()) to wait for input if possible * * The return value is the number of bytes read, or < 0 for EOF. * * Unfortunately, systems that get interrupted from slow reads update * this access time for the terminal (in violation of POSIX). * The fixtime() macro resets the time to the time at entry in - * this case. This is not necessary for systems that can handle - * sfpkrd() correctly (i.e., those that support poll() or select()). + * this case. This is not necessary for systems that have select(). */ int ed_read(void *context, int fd, char *buff, int size, int reedit) { @@ -851,11 +850,12 @@ int ed_read(void *context, int fd, char *buff, int size, int reedit) Shell_t *shp = ep->sh; int mode = -1; int (*waitevent)(int,long,int) = shp->gd->waitevent; + /* sfpkrd must use select(2) to intercept SIGWINCH for ed_read */ if(ep->e_raw==ALTMODE) - mode = 1; + mode = 2; if(size < 0) { - mode = 1; + mode = 2; size = -size; } sh_onstate(SH_TTYWAIT); diff --git a/src/lib/libast/sfio/sfpkrd.c b/src/lib/libast/sfio/sfpkrd.c index 91f56974c..1295e5cd9 100644 --- a/src/lib/libast/sfio/sfpkrd.c +++ b/src/lib/libast/sfio/sfpkrd.c @@ -24,11 +24,12 @@ /* * The preferred method is POSIX recv(2) with MSG_PEEK, which is detected as 'socket_peek'. * On Solaris/Illumos (__sun), _stream_peek and _lib_select are needed, as _socket_peek doesn't work correctly. - * On at least macOS and Linux, sfpkrd() runs significantly faster if we disable these. + * On at least macOS and Linux, sfpkrd() runs significantly faster if we disable these. However, + * ed_read() still needs to use select to intercept SIGWINCH, so if the last argument given + # to sfpkrd is '2' select is always used when available. */ #if _socket_peek && !__sun #undef _stream_peek -#undef _lib_select #endif #if __APPLE__ && !_socket_peek @@ -55,6 +56,7 @@ long tm; /* time-out */ int action; /* >0: peeking, if rc>=0, get action records, <0: no peeking, if rc>=0, get -action records, =0: no peeking, if rc>=0, must get a single record + =2: same as >0, but always use select(2) */ #endif { @@ -118,7 +120,11 @@ int action; /* >0: peeking, if rc>=0, get action records, (t&SOCKET_PEEK) ) { r = -2; #if _lib_select - if(r == -2) + if(r == -2 +#if !__sun /* select(2) is always used on Solaris or if action == 2 on other OSes */ + && action == 2 +#endif + ) { fd_set rd; struct timeval tmb, *tmp; FD_ZERO(&rd);