The first solution is mostly for multi-threaded BLAS libraries, but it also works here indicating some dependence on threads.

The second case is pretty interesting. A simple example that seems to reset the interrupt handlers is

All this does is call system and ask for the output back. Internally, it seems that it is the creation of an iprocstream which probably resets things. This is more easily proved by the following which also works

and the code in file-io.cc is

Just for fun, I commented out the retval statement and it still works so it is really the one statement to create an iprocstream that fixes things.

So, maybe jwe has an idea, but it seems that during the start-up sequence there is a lot of forking/execing and maybe not all of the std::streams get associated with the correct PID.

I haven't seen this problem, because apparently the following line causes this to start working (explicitly shown here to cause a change in the way the terminal interrupts are handled):

My ~/.octaverc actually calls gnuplot, but the program that is called in system() doesn't seem to matter, what matters is that the output is captured with nargout == 2. This is enough to apparently restore terminal interrupt handling enough so that this works.

May have something to do with the octave-gui executable and doing something to the terminal attributes when it starts up.

Yes, I think jwe's patch is better than what we have now, It works for me for the subprocess example, doesn't break any of the other cases for me, assuming OMP_NUM_THREADS=1. FIXME makes it clear we need some more work done to make this better.

Incidentally, are braces required in this case where it's a single line of code but multiple lines of comments?

Using jwe's patch from comment #51, the only failing instance from test #3 works. However, jwe indicated in comment #51 that perhaps it should not be applied because it could lead to segfaults in multi-threaded BLAS libraries.

However, we already have that problem (bug #47400), so can we apply this anyways?

Octave's handling of Ctrl+C interrupts is seriously compromised. To begin with, I did all my testing on Linux (most stable of the OSes we support) with an up to date development tip (21835:f250714c629d). I can repeatedly, and easily, get segfaults which lose all the work in the interpreter. This is serious, so I have changed the severity to Blocker for the 4.2 release.

Test #1

I used Thorsten's code from comment #6 as the test vehicle. I've attached that code to the bug report as tst_ctrlc.m.

Steps to reproduce:

Results:

Test #2

Try to interrupt pause, which has always been problematic and has a different implemenation on Windows versus Linux. See bug #44470 for a more complete description of the problems specific to Windows.

Steps to reproduce:

Results:

Test #3

Try to interrupt a call to system() which has created a child process.

Steps to reproduce:

Results:

This appears to be multiple bugs manifesting in roughly the same way. The segfault in test #1 is most likely due to the multithreaded nature of the BLAS library. If I use

before starting run-octave then I no longer get segfaults and Ctrl+C seems to work.

Similarly, pause() has very different implementations between operating systems and it is likely that each OS needs that bit of code adapted in order to resolve test #2.

For test #3, it looks like the issue will be who is receiving the Ctrl+C indication. Is it the embedded terminal process, the GUI Shortcut Manager, Qt itself, someone else?

My suggestion is that we start by building our understanding on the Linux platform and getting that to work correctly in 100% of cases. From there, we can take what we know and apply it to solutions for Mac and Windows platforms.

A lot of work has been done on the Ctrl+C processing in the GUI. Can someone who was experiencing this error try the octave 4.0.0-rc4 available at ftp://alpha.gnu.org/gnu/octave/ and check if the problem is fixed?

I'm attaching a change that allows system() to be interrupted when running Octave with the GUI on Unixy systems. However, I don't think we can use this change because it will make Octave crash when interrupting calls to multi-threaded BLAS functions, for example.

The only other thing I can think of is to somehow get (or track) the list of processes that are in the same process group as Octave and send SIGINT to all of them except the Octave process and then use pthread_kill to send SIGINT to the Octave interpreter thread. Is there some easy way to get the list of processes in the process group? If not, then it will take some work to keep track of the processes that we create, and it won't be possible to track all of the processes that might be created in .oct files (for example).

It's unclear to me what has been fixed and should work now, I haven't been following too closely.

Built tonight, I can interrupt long-running Octave functions, but interrupts do not seem to be sent on to child processes invoked from Octave, e.g. through system(). Is this expected or should be working now?

Doing either system("sleep 30") or system("watch ls") in the GUI results in something that can't be interrupted at all.

Also making "less" come up and then pressing "F" to enter tail mode results in something that can't be interrupted (this was reported in another bug that I marked as a duplicate of this one).

How did you build? Rik mentioned that he had trouble until he built from scratch. I don't know whether that is really needed, but maybe there was some problem with the build for you that causes trouble.

This seems to fix the problem for me with signal handling and the --no-gui option. It should work on systems that use pthreads. It won't do anything for us on Windows systems. I'll post something on the maintainers list about signal handling and Windows.

Good. For the 3.8 release making --no-gui mean --no-gui-libs
seems fine. Getting Qt GUI elements to work can be done
later. Just having GUI or --no-gui is better than three flavors
anyhow. And, there is enough work on blockers already.

So, I am for making --no-gui mean --no-gui-libs. If it is
needed for testing Qt in no-gui mode some other temporary
mechanism can be used.

I mean that Qt GUI elements will not work from the command line interface. FLTK plotting will still work. But we would like to use Qt widgets for plotting and UI elements, and I think that should work from the command line. Michael Goffioul had that working with QtHandles, though I'm not sure what the status of interrupt handling was with his wrapper program that set up the Qt application context.

The idea is for --no-gui-libs to bring up a command-line only version of Octave in which graphics and any graphical user interface elements might not even work. The --no-gui option should start Octave in a command-line mode that still allows graphics and ui* functions to work. But currently the --no-gui thing is not really working, so I'm beginning to think that we should just make --no-gui mean the same as --no-gui-libs for the 3.8 release. Then interrupt handling is solved for those two cases. It also looks like the pthread_kill/pthread_sigmask thing works for the GUI in Unix systems. Then we are just left with making interrupts work properly for Windows systems.

I also had the same problem where Ctrl+C was not recognized after just doing "hg pull; hg update; make". In the end, 'make clean' and 'make distclean' were not enough. I had to run 'make maintainer-clean' and then also delete libgui/src/src_libgui_src_la-octave-main-thread.lo. Then I re-ran the bootstrap, configure, and make cycle.

What happens if you execute "sleep (200)" at the Octave prompt and then do "kill -INT PID" with PID == the process ID of the Octave process? This should be the one that is shown as "octave" in the output from ps, not the "lt-octave-gui" process.

Does that deliver an interrupt signal to Octave? If so, does it interrupt the sleep function?

I'm trying to determine whether it is a problem with Ctrl-C not being acted on by Qt (we expect that it is defined as a keyboard shortcut that will eventually put us in the copyClipboard function in the terminal widget) or if it is that signal handling is not working.

On Windows, interrupting a loop like "more off; for i = 1:100000, i, end" should work, but interrupting an external library function like "inv (large_matrix)" probably won't work becuase the setjmp/longjmp thing fails.

I did a full maintainer-clean, followed by bootstrap, configure, make to get rid of any cruft. After getting past the missing config.h include in octave-dock-widget.cc, I now have Ctrl+C working on a Mint (Debian-derivative) system. I will try and cross-compile for MinGW and see how it works over there.

What happens if you execute "sleep (200)" at the Octave prompt and then do "kill -INT PID" with PID == the process ID of the Octave process? This should be the one that is shown as "octave" in the output from ps, not the "lt-octave-gui" process.

Also, what happens if you select some text in the command window and type Ctrl-C? Does it paste the selected text?

Does Ctrl-C give you a new prompt when Octave is otherwise idle and waiting for input?

Does Ctrl-C interrupt loops like "more off; for i = 1:1000000; i, end"?

Michael, what happens if you type Ctrl-C when inv is working on a large matrix? For example

Pause for a half second or so before interrupting the inv command because there is a call to std::copy at the top of that function that must complete before you get to the code that will react to SIGINT by doing a longjmp. If you type Ctrl-C twice while the std::copy is working, you'll get a message about typing Ctrl-C again to abort Octave. If you do that before reaching the code where Octave uses setjmp/longjmp, you'll exit Octave.

What about if you go back to the changeset prior to my latest patches? Try "hg up -C c9f622fd7307", then build again and try the test above. I expect that Octave will exit when you type Ctrl-C, and that will happen without the message about typing Ctrl-C again to abort. So without the patches, interrupting doesn't work properly. With them, I'm hoping that it is just sleep that is affected.

In 3.7.6+ GUI (MXE-cross-built, on WinXP), trying to interrupt 'system ("sleep 50")' doesn't work. I get after Ctrl-C twice separated three secs apart:

...and the next (3rd) Ctrl-C kills Octave with an error about
"The instruction at '0x67777e70' referencing memory at '0x00000000'. The memory could not be read
Click OK to terminate the program"

I tend to suspect this is due to Octave calling an external program; either Octave doesn't correctly transfer the interrupt to sleep(), or sleep() itself doesn't want to be interrupted (improbable I think), or Octave doesn't correctly pick up sleep()'s return. I'd go for the first because sleep() goes on and on.... it apparently never gets the signal.

Setting status back to confirmed since we have a couple of cases here that are not responding to user interrupt correctly.

Here's another one:

In the command line, any child process receives the SIGINT, in this case the command exits immediately and the exit status is non-zero.

Same with the 'F' command in the less pager, which runs to the end of the input and waits for a user interrupt. If it cannot be interrupted, it never returns and Octave has to be killed. See bug #37468 (assigning as a duplicate of this bug now).

In the GUI both of these examples just hang, the child process does not receive the SIGINT.

I do see that ctrl-c does cancel the current line being edited if no text is selected. It also does break out of a long-running for loop. But I don't see the following working in the GUI, which works fine in terminal mode:

first ctrl-c: nothing happens
second ctrl-c: "Press Control-C again to abort."
third ctrl-c: Octave exits

So the interrupt is being caught by sigint_handler, but does not break the sleep function.

I'm running an external binary for my numerical simulations using the octave "unix" command and it is this process the Octave-GUI can't interrupt.
As a matter of fact, I can't exit the GUI at all. The close button or File->Exit do not react as well. Not even a normal process kill (SIGTERM) does it.
After the unix command finishes the GUI crashes.. but only if I tried to abort it with CTRL+C

With the "no-gui", octave reacts as expected and as I mentioned so does the GUI and no-gui version for Windows (mxe build).

Changeset http://hg.savannah.gnu.org/hgweb/octave/rev/eefcfeb37446
fixes the issue on my system (ubuntu). The terminal already aborted a command with the copy shortcut but this was configured to ctrl+shift+c up to now. Just configuring to the right shortcut ctrl+c solved the problem.

I am leaving the report open until the fix is confirmed on other systems.

If running a long command or script within the new Octave GUI it cannot be aborted with CTRL+C (or any other way) since it is not recognized!

I like the new GUI very much, but I run very lengthy numerical simulations and not being able to abort them is a real show-stopper for me. I have to kill (no reacting to quit or CTRL+Q either) the GUI and restart every time losing my workspace & results in the process...