summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMartijn van Duren <martijn@cvs.openbsd.org>2021-08-11 15:13:47 +0000
committerMartijn van Duren <martijn@cvs.openbsd.org>2021-08-11 15:13:47 +0000
commit6dcd911f8f560797d1b0ab31ae6b534bbe480bba (patch)
treed8644a0782c613dddd810c1fe56353efd2f59b0b /lib
parent2d49304fff5cb7247f09a85b1589b54210155e48 (diff)
Only enter the sig_no switch if we actually return from read(2) with
errno == EINTR. There was a race here where read(2) can return with a different errno, but the signal handler enters between the read return and the switch, which could result in handling a signal, while we should be handling the error. This fix assumes that signal handlers don't clobber our errno, but doing that would open a whole other can of worms. OK schwarze@, millert@
Diffstat (limited to 'lib')
-rw-r--r--lib/libedit/read.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/lib/libedit/read.c b/lib/libedit/read.c
index 754d898a222..7900193aecc 100644
--- a/lib/libedit/read.c
+++ b/lib/libedit/read.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: read.c,v 1.46 2021/08/10 14:28:10 schwarze Exp $ */
+/* $OpenBSD: read.c,v 1.47 2021/08/11 15:13:46 martijn Exp $ */
/* $NetBSD: read.c,v 1.100 2016/05/24 19:31:27 christos Exp $ */
/*-
@@ -240,15 +240,17 @@ read_char(EditLine *el, wchar_t *cp)
el->el_signal->sig_no = 0;
while ((num_read = read(el->el_infd, cbuf + cbp, 1)) == -1) {
int e = errno;
- switch (el->el_signal->sig_no) {
- case SIGCONT:
- el_set(el, EL_REFRESH);
- /*FALLTHROUGH*/
- case SIGWINCH:
- sig_set(el);
- goto again;
- default:
- break;
+ if (errno == EINTR) {
+ switch (el->el_signal->sig_no) {
+ case SIGCONT:
+ el_set(el, EL_REFRESH);
+ /*FALLTHROUGH*/
+ case SIGWINCH:
+ sig_set(el);
+ goto again;
+ default:
+ break;
+ }
}
if (!tried && read__fixio(el->el_infd, e) == 0) {
errno = save_errno;