Here's a WIP version of CTRL-C handling for Win32. Although there are still some minor issues to tackle (see below), it seems to work decently and reliably. I've tested it in CLI and GUI and I can interrupt m-code execution as well as interruptible native code (typically a LAPACK/BLAS routine). I can do it multiple times and so far it hasn't crashed on me.
One main issue I'd like to raise and discuss is the interaction with readline. Basically when you combine octave (using gnulib), readline (not using gnulib) and the fact that Win32 does not have siglongjmp, you start having conflicting situations.
Typically, readline installs its own SIGINT handler, but also store the previous handler for later use. During SIGINT handling, it does some internal clean-up, restore the previous handler, than "raise(SIGINT)" to execute the previous handler.
OTOH, octave uses gnulib. The gnulib's signal handling is along those lines: block the signal, execute the handler, unblock the signal. If the signal handler performs a longjmp, the signal will stay in "blocked" state (in gnulib, this translates into having a dummy handler that does nothing). Now the problem is that on the next run of readline, the stored handler will be the gnulib's dummy one, and CTRL-C will end up being ignored while being in readline loop. This does not happen on platforms having sigsetjmp/siglongjmp, or more generally on POSIX platforms.
I've worked around that issue by installing octave_interrupt_hook and make sure SIGINT is handled after an interrupt. Another way, which I tested, is to disable signal handling in readline by setting rl_catch_signals to 0, but I'm not sure to what extend this is a problem in readline itself.
There are other remaining issues, but I believe these are minor:
- in CLI mode, readline doesn't react to CTRL-C; this is because readline then uses _getch(), and this function disable CTRL-C processing; instead, CTRL-C are fed as character 0x3 into the input buffer; I suppose this could be worked around by having octave install a CTRL-C handler in readline and raise SIGINT
- "sleep" is not interruptible in Win32, at least not when compiled with MSVC; octave uses the gnulib implementation, which calls Win32 "Sleep" in a for loop; that code is not surrounded by setjmp/longjmp, so it's not interruptible (if you use CTRL-C 3 times, you end up aborting octave)