1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-10 12:40:58 +02:00

40170: Fix up error resetting in curses module.

Update comment to remove confusion.  The comment was based on
incorrecto expectations, and the problems referred to seem to be fixed.
This commit is contained in:
Sebastian Gniazdowski 2017-03-02 23:48:09 -08:00 committed by Peter Stephenson
parent efe5e6a2f0
commit c8005af310
2 changed files with 17 additions and 23 deletions

View file

@ -1,5 +1,10 @@
2017-03-03 Peter Stephenson <p.stephenson@samsung.com> 2017-03-03 Peter Stephenson <p.stephenson@samsung.com>
* Sebastain: 40170: Src/Modules/curses.c: Fix up error number
resetting in curses module. This appears to resolve an issue
mentioned in comments but attributed elsewhere, so remove
confusion here.
* 40173: Test/V11db_gdbm.ztst: don't report an error if gdbm * 40173: Test/V11db_gdbm.ztst: don't report an error if gdbm
module doesn't load as this simply causes the test to be skipped. module doesn't load as this simply causes the test to be skipped.

View file

@ -1082,15 +1082,7 @@ zccmd_input(const char *nam, char **args)
#endif #endif
/* /*
* Some documentation for wgetch() says: * Linux, OS X, FreeBSD documentation for wgetch() mentions:
The behavior of getch and friends in the presence of handled signals
is unspecified in the SVr4 and XSI Curses documentation. Under his-
torical curses implementations, it varied depending on whether the
operating system's implementation of handled signal receipt interrupts
a read(2) call in progress or not, and also (in some implementations)
depending on whether an input timeout or non-blocking mode has been
set.
Programmers concerned about portability should be prepared for either Programmers concerned about portability should be prepared for either
of two cases: (a) signal receipt does not interrupt getch; (b) signal of two cases: (a) signal receipt does not interrupt getch; (b) signal
@ -1098,21 +1090,16 @@ zccmd_input(const char *nam, char **args)
EINTR. Under the ncurses implementation, handled signals never inter- EINTR. Under the ncurses implementation, handled signals never inter-
rupt getch. rupt getch.
* The observed behavior, however, is different: wgetch() consistently * Some observed behavior: wgetch() returns ERR with EINTR when a signal is
* returns ERR with EINTR when a signal is handled by the shell "trap" * handled by the shell "trap" command mechanism. Observed that it returns
* command mechanism. Further, it consistently returns ERR twice, the * ERR twice, the second time without even attempting to repeat the
* second time without even attempting to repeat the interrupted read, * interrupted read. Third call will then begin reading again.
* which has the side-effect of NOT updating errno. A third call will
* then begin reading again.
* *
* Therefore, to properly implement signal trapping, we must (1) call * Because of widespread of previous implementation that called wget*ch
* wgetch() in a loop as long as errno remains EINTR, and (2) clear * possibly indefinitely many times after ERR/EINTR, and because of the
* errno only before beginning the loop, not on every pass. * above observation, wget_wch call is repeated after each ERR/EINTR, but
* * errno is being reset (it wasn't) and the loop to all means should break.
* There remains a potential bug here in that, if the caller has set * Problem: the timeout may be waited twice.
* a timeout for the read [see zccmd_timeout()] the countdown is very
* likely restarted on every call to wgetch(), so an interrupted call
* might wait much longer than desired.
*/ */
errno = 0; errno = 0;
@ -1120,6 +1107,7 @@ zccmd_input(const char *nam, char **args)
while ((ret = wget_wch(w->win, &wi)) == ERR) { while ((ret = wget_wch(w->win, &wi)) == ERR) {
if (errno != EINTR || errflag || retflag || breaks || exit_pending) if (errno != EINTR || errflag || retflag || breaks || exit_pending)
break; break;
errno = 0;
} }
switch (ret) { switch (ret) {
case OK: case OK:
@ -1146,6 +1134,7 @@ zccmd_input(const char *nam, char **args)
while ((ci = wgetch(w->win)) == ERR) { while ((ci = wgetch(w->win)) == ERR) {
if (errno != EINTR || errflag || retflag || breaks || exit_pending) if (errno != EINTR || errflag || retflag || breaks || exit_pending)
return 1; return 1;
errno = 0;
} }
if (ci >= 256) { if (ci >= 256) {
keypadnum = ci; keypadnum = ci;