On 11/23/17 10:52 AM, Rin Okuyama wrote:
Thank you for your comment. As you pointed out, the signal check
should be within the select(2) loop. New versions would be
(1) _rl_signal_handler() is used as before:
----
int getc_wrapper(FILE *fp) {
fd_set fds;
int fd = fileno(fp);
int ierr;
if (external_fd >= 0) {
do {
FD_ZERO(&fds);
FD_SET(fd, &fds);
FD_SET(external_fd, &fds);
ierr = select(external_fd + 1, &fds, 0, 0, NULL);
if (ierr < 0 && errno == EINTR) {
#ifdef HAVE_LIBREADLINE
if (_rl_caught_signal)
_rl_signal_handler(_rl_caught_signal);
#endif
continue;
}
... poll and read from external_fd ...
} while (!FD_ISSET(fd, &fds));
}
#ifdef HAVE_LIBREADLINE
return rl_getc(fp);
#else
return getc(fp);
#endif
}
----
(2) the 1st ifdef block is simply replaced by
----
#ifdef HAVE_LIBREADLINE
return rl_getc(fp);
#endif
----
Both (1) and (2) suspend by Control-z. However, variant (2) does not
accept input from external_fd (it is actually mouse driver) after
continue from suspend, unless the first any input arrives from tty.
I guess that this is inevitable with rl_getc(). How do you think?
This isn't what I said. You only want to call rl_getc in that scenario
unless you're sure that the select() was interrupted by a signal, because
what you're interested in is the side effect of its signal handling.
You can either break out of the loop, in which case the call to rl_getc
following the loop will (as a side effect) handle the signal, or you
can call it explicitly. If you call it in the loop, you only want to
call it if you're sure you have a signal handler call pending to avoid
the case you encountered. So something like (readline-7.0):
if (ierr < 0 && errno == EINTR)
if (rl_pending_signal ()) return rl_getc ();