bug-readline
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-readline] [PATCH] Gnuplot on macOS does not suspend by Control-


From: Chet Ramey
Subject: Re: [Bug-readline] [PATCH] Gnuplot on macOS does not suspend by Control-z
Date: Wed, 22 Nov 2017 15:47:55 -0500
User-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:52.0) Gecko/20100101 Thunderbird/52.4.0

On 11/22/17 5:07 AM, Rin Okuyama wrote:
> Thank you for your kind reply!
> 
>> Does GNUplot install a handler for SIGTSTP or ignore it? The behavior
>> you describe, in the absence of any other changes, sounds like something
>> sets the DSUSP character to ^Z.
> 
> No, it does not install any signal handlers.
> 
>> It must be something specific to GNUplot, since the simple readline test
>> programs handle ^Z as expected when run on MacOS.
> 
> I examined differences between the sample programs and gnuplot, then
> I found that gnuplot specifies its own wrapper for getc(3) to
> rl_getc_function:
> 
> ----
> 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);
>             ...
>         } while (!FD_ISSET(fd, &fds));
>     }
>     return getc(fp);
> }
> ----
> (This is a simplified version. Please refer to getc_wrapper() in
> src/plot.c and X11_waitforinput() in term/x11.trm for more details.)
> 
> The reasons why gnuplot does not suspend by Control-z, and does by
> any key following Control-z are,
> 
> (1) when external_fd >= 0, select(2) cannot catch SIGTSTP, and
> (2) when external_fd < 0, getc(3) cannot catch SIGTSTP
> 
> Therefore I modified the code as below:
> 
> ----
> 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);
> #ifdef HAVE_LIBREADLINE
>             extern int _rl_caught_signal;
>             void _rl_signal_handler(int);
>             if (_rl_caught_signal)
>                 _rl_signal_handler(_rl_caught_signal);
> #endif
>             ierr = select(external_fd + 1, &fds, 0, 0, NULL);
>             ...
>         } while (!FD_ISSET(fd, &fds));
>     }
> #ifdef HAVE_LIBREADLINE
>     int rl_getc(FILE*);
>     return rl_getc(fp);
> #else
>     return getc(fp);
> #endif
> }
> ----
> 
> Then, it successfully suspends regardless of external_fd.
> 
> However, as you can see, this is a kind of dirty hack. I wonder whether
> there are some portable ways to do like this? I guess that rl_getc() in
> the second ifdef block can be replaced by something like this:
> 
> ----
> int (*readline_getc)(FILE*) = NULL;
> ...
> readline_getc = rl_getc_function;
> rl_getc_function = getc_wrapper;
> ...
> int gnuplot_getc(FILE *fp) {
>     if (readline_getc)
>         return readline_getc(fp);
>     else
>         return getc(fp);
> }
> ----
> 
> But, how about the first ifdef block?

In bash-4.4/readline-7.0, there is a new public function:
rl_pending_signal(), which will return the value of _rl_caught_signal.
There's no good public way to call _rl_signal_handler().  If you don't
want to mess with calling a semi-private readline function, you can
just call rl_getc(), since the first thing it does is check for and
handle any pending signals.

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    address@hidden    http://cnswww.cns.cwru.edu/~chet/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]