[Top][All Lists]

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

interrupt handing and the GUI (bug #37672)

From: John W. Eaton
Subject: interrupt handing and the GUI (bug #37672)
Date: Sun, 10 Nov 2013 12:07:57 -0500
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130116 Icedove/10.0.12

I have marked bug 37672 (https://savannah.gnu.org/bugs/?37672) as a
blocker for the release.  I have some ideas about why this is not
working and what we can do to fix it.

In the CLI version of Octave, the terminal driver sends a SIGINT
signal to the Octave process when the user types Ctrl-C at the
command prompt.  Then the SIGINT signal is caught and we end up in the
function user_abort.

In the GUI, typing Ctrl-C in the terminal window doesn't generate a
SIGINT signal directly as it does when Octave is running in a
terminal.  Instead, it eventually calls the function
TerminalView::copyClipboard (in the Unix version of the libqterminal
code) or QWinTerminalImpl::copyClipboard (in the Windows version of
the libqterminal code).  Then, if there is no selection, we call
::raise (SIGINT) to generate an interrupt signal for the process.
From there, we end up in user_abort.

Ignoring things like "debug_on_interrupt", the function user_abort
may do one of two things to handle the signal.

The first is to set the global variable octave_interrupt_state and
return.  Then Octave periodically checks this variable (typically
using the OCTAVE_QUIT macro) and if it is set, throws an exception and
returns to the command prompt.

This method of interrupt handling works in the CLI and GUI versions of
Octave.  This is how interrupts inside loops like

  while (true) disp ('foo-i-hithere'); end

are handled.

The second method of signal handling is to call the function
jump_to_enclosing_context, which calls longjmp to return to a "safe"
location at which point Octave throws an exception and returns to the
command prompt.

This type of interrupt handling is used when we need to be able to
interrupt calls to library functions that we don't have control over
so we can't insert calls to OCTAVE_QUIT to make them abort.  This
method works for the CLI version of Octave but not with the GUI.  The
difference is that in the CLI version, we only have one thread but in
the GUI, we have multiple threads and the exception is being thrown in
the thread where the GUI is running instead of the thread where the
Octave interpreter is running.

I was able to examine this behavior by using "info threads" in gdb
while doing something like

  x = rand (3000);
  inv (x);

in Octave and typing Ctrl-C in the command window when Octave is busy
working on the inverse.

My first thought was that we need to make sure that the SIGINT signal
and interrupt handler are executed inside the same thread where Octave
is running, so instead of simply calling ::raise inside the
copyClipboard function, I modified Octave to emit a Qt signal there
that would be handled by a Qt slot function running in the Octave
interpreter thread.  Of course this doesn't work because in that
thread the Octave interpreter never returns to give control back to
the Qt thread manager.

Here is my proposed solution:

Instead of using setjmp/longjmp and relying on Unix signal handling to
interrupt the process, we execute these long-running external
functions in separate threads that we can cancel when an interrupt
arrives.  Then in the main thread we just wait for the thread to
finish and periodically check to see whether the
octave_interrupt_state variable is set.  If it is, then we cancel the
thread and throw an exception.  That will all happen inside the thread
that is running the Octave interpreter, so we won't be trying to throw
an exception across threads.

I understand how to do this with pthreads.  I'll either need help with
Windows threads or maybe we could use the pthreads-win32 library
(LGPL; available here: http://www.sourceware.org/pthreads-win32).

Another question is whether we should always use this approach or
continue to use the setjmp/longjmp method for the CLI version of

Does anyone see a better way?


reply via email to

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