Hi David,
thank you very much. I read the paragraph below several times. Unfortunately
the behavior of readline is somewhat different. The problem seemed to be
that
signal handling is "too transparent" in that it ignores settings made in
the signal
handler.
But I am on the way towards a solution. The first ingredient was Blakes
recommendation
to bind ^C. That was correct, except that it didn't work. It worked for
^A, ^B, etc but
not for ^C. The missing piece was to entirely hide ^C's special role
from readline
before calling readline(). After that ^C could be bound like any other
^something.
I am currently running a number of tests with this and I am hoping that
I can commit
the solution tomorrow. That should include your ^C comments and also
Blake's printout
issues.
/// Jürgen
On 07/22/2014 08:03 PM, David Lamkins wrote:
J'uergen,
I noticed this paragraph in the readline documentation:
" Readline contains an internal signal handler that is installed for a
number of signals (`SIGINT', `SIGQUIT', `SIGTERM', `SIGALRM',
`SIGTSTP', `SIGTTIN', and `SIGTTOU'). When one of these signals is
received, the signal handler will reset the terminal attributes to
those that were in effect before `readline()' was called, reset the
signal handling to what it was before `readline()' was called, and
resend the signal to the calling application. If and when the calling
application's signal handler returns, Readline will reinitialize the
terminal and continue to accept input. When a `SIGINT' is received,
the Readline signal handler performs some additional work, which will
cause any partially-entered line to be aborted (see the description of
`rl_free_line_state()' below)."
The way I read this, readline() should be transparent w.r.t. ^C.
Readline resignals your app, then resets *itself* when control returns
from your app's signal handler.
I believe that it's a mistake (or at best, needless) to call
rl_delete_text() from Input::got_control_C(), but that's not the crux
of the problem.
The real problem seems to be that readline() isn't seeing rl_done. In
the context of the above-quoted paragraph, though, this may be
explained by: " If and when the calling application's signal handler
returns, Readline will reinitialize the terminal and continue to
accept input". My best guess is that the reinitialization also affects
other state in readline and clobbers the signal handler's having set
rl_done.
That's my best working hyphothesis at this point.
I can envision a couple ways to deal with this:
1. Build some additional scaffolding using setjmp() and longjmp(). The
idea is that a longjmp() from the handler would return *after* the
readline() call. Note the need to call rl_cleanup_after_signal() in
this case.
2. Look for a readline hook that gets called after the
reinitialization that's supposedly done after return from the signal
handler. Consider rl_startup_hook and rl_pre_input_hook. The idea is
that the hook function would test the value of attention_raised (and
interrupt_raised) and set rl_done.
I'd start with (2). The thought of setjmp()/longjmp() in a C++ program
makes me itch... ;)
If you don't get to this today, I may have some time tonight to
experiment with case (2).
On Tue, Jul 22, 2014 at 7:36 AM, Juergen Sauermann
<juergen.sauerm...@t-online.de <mailto:juergen.sauerm...@t-online.de>>
wrote:
Hi Blake,
I tried, but it did not work.
The deeper I go into readline the more weird it gets.
If I do nothing then I get the first ^C delivered as signal but
not subsequent ones.
I would have preferred if two ^Cs (i.e. INTERRUPT rather than
ATTENTION) would
stop printouts, but readline delivers only one.
I also tried binding to ^C; interestingly I can bind to any other
key except ^C. The
bind to ^C succeeds (returns no error) but the function bound to
it is not
called. For other keys this works.
/// Jürgen
On 07/21/2014 08:12 PM, Blake McBride wrote:
Does this help?
This may be related to the cooked/uncooked/rare
<http://en.wikipedia.org/wiki/POSIX_terminal_interface#Early_Unices%3a_Seventh_Edition_Unix>
terminal
modes; |^C| does not always send a signal. It seems likely that
readline uncooks the terminal, and thus any signals caused by
keyboard input must be due to logic within readline itself; it
seems plausible that it might only trigger a SIGINT on two
sequential |^C|s (especially since for many programs that utilise
readline such as shells and REPLs, the program exiting on a
single |^C| would be very annoying!).
You might be able to change this behaviour by using the readline
API to rebind |^C| to some of your own code that triggers a
SIGINT. I haven't used readline from Haskell, just from C, so I'm
not sure exactly how you'd go about this, but the binding
<http://hackage.haskell.org/packages/archive/readline/latest/doc/html/System-Console-Readline.html>
seems
rich enough to achieve it.
/Blake McBride/
/
/
www.arahant.com <http://www.arahant.com/>
Cell: 615-394-6760 <tel:615-394-6760>
Office: 615-376-5500 <tel:615-376-5500>
Fax: 615-377-6006 <tel:615-377-6006>
--
"Far out in the uncharted backwaters of the unfashionable end of the
Western Spiral arm of the Galaxy lies a small unregarded yellow sun.
Orbiting this at a distance of roughly ninety-eight million miles is
an utterly insignificant little blue-green planet whose ape-descended
life forms are so amazingly primitive that they still think
programming in Java is a pretty neat idea."
-- With apologies to Douglas Adams, who I like to think would have
appreciated this.
http://soundcloud.com/davidlamkins
http://reverbnation.com/lamkins
http://reverbnation.com/lcw
http://lamkins-guitar.com/
http://lamkins.net/
http://successful-lisp.com/