zsh-users
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: zsh-users@zsh.org
Subject: Re: Signal handling/zcurses
Date: Fri, 22 Apr 2011 07:22:01 -0700	[thread overview]
Message-ID: <110422072201.ZM32160@torch.brasslantern.com> (raw)
In-Reply-To: <110421225257.ZM14169@torch.brasslantern.com>

On Apr 21, 10:52pm, Bart Schaefer wrote:
} Subject: Re: Signal handling/zcurses
}
} If you interrupt "zcurses input" with a handled signal, wget_wch() [and
} I must assume wgetch()] returns ERR/EINTR.  The loop in my patch then
} calls it again and gets ERR/zero, which causes "zcurses input" to
} return 1.

Let's try this patch instead.

Note - this change may still be incomplete.  When the "read" builtin is
interrupted its implementation checks various global shell conditions in
addition to the errno state.  It's not clear to me which of those should
be checked here.


Index: Src/Modules/curses.c
===================================================================
RCS file: /extra/cvsroot/zsh/zsh-4.0/Src/Modules/curses.c,v
retrieving revision 1.4
diff -c -r1.4 curses.c
--- curses.c	4 Nov 2008 04:47:53 -0000	1.4
+++ curses.c	22 Apr 2011 14:12:41 -0000
@@ -1069,8 +1069,47 @@
     }
 #endif
 
+    /*
+     * Some documentation for wgetch() says:
+
+       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
+       of  two cases: (a) signal receipt does not interrupt getch; (b) signal
+       receipt interrupts getch and causes it to return ERR with errno set to
+       EINTR.  Under the ncurses implementation, handled signals never inter-
+       rupt getch.
+
+     * The observed behavior, however, is different:  wgetch() consistently
+     * returns ERR with EINTR when a signal is handled by the shell "trap"
+     * command mechanism.  Further, it consistently returns ERR twice, the
+     * second time without even attempting to repeat the interrupted read,
+     * 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
+     * wgetch() in a loop as long as errno remains EINTR, and (2) clear
+     * errno only before beginning the loop, not on every pass.
+     *
+     * There remains a potential bug here in that, if the caller has set
+     * 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;
+
 #ifdef HAVE_WGET_WCH
-    switch (wget_wch(w->win, &wi)) {
+    while ((ret = wget_wch(w->win, &wi)) == ERR) {
+	if (errno != EINTR)
+	    break;
+    }
+    switch (ret) {
     case OK:
 	ret = wctomb(instr, (wchar_t)wi);
 	if (ret == 0) {
@@ -1092,9 +1131,10 @@
 	return 1;
     }
 #else
-    ci = wgetch(w->win);
-    if (ci == ERR)
-	return 1;
+    while ((ci = wgetch(w->win)) == ERR) {
+	if (errno != EINTR)
+	    return 1;
+    }
     if (ci >= 256) {
 	keypadnum = ci;
 	*instr = '\0';


  reply	other threads:[~2011-04-22 14:22 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-20 10:19 Anthony Charles
2011-04-20 14:40 ` Bart Schaefer
2011-04-20 19:22   ` Anthony Charles
2011-04-21  8:48     ` Bart Schaefer
2011-04-21 14:31       ` Anthony Charles
2011-04-21 15:47         ` Bart Schaefer
2011-04-21 18:08           ` Anthony Charles
2011-04-22  3:07             ` Bart Schaefer
2011-04-22  5:52               ` Bart Schaefer
2011-04-22 14:22                 ` Bart Schaefer [this message]
2011-04-27  8:38                   ` Anthony Charles
2011-04-21 18:29           ` Anthony Charles

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=110422072201.ZM32160@torch.brasslantern.com \
    --to=schaefer@brasslantern.com \
    --cc=zsh-users@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).