Mercurial > hg > octave-nkf
changeset 17958:1adf3710bb68
Working CTRL-C handling implementation for Win32.
* libgui/src/thread-manager.cc (sighandlers.h): New include.
(windows_thread_manager::interrupt): Call w32_raise_sigint instead of
::raise.
* libinterp/corefcn/sighandlers.h (w32_raise_sigint): New declatation.
* libinterp/cirefcn/sighandlers.cc (user_abort): Forward declare.
(class w32_interrupt_manager): New singleton helper class.
(w32_raise_sigint): New function.
(user_abort): Call
w32_interrupt_manager::octave_jump_to_enclosing_context instead of
octave_jump_to_enclosing_context on Win32 platform.
(sigint_handler): Call w32_interrupt_manager::user_abort instead of
user_abort on Win32 platform.
(octave_catch_interrupts, octave_ignore_interrupts,
octave_set_interrupt_handler): Call w32_interrupt_manager::init on
Win32 platform.
* liboctave/util/oct-rl-edit.c (octave_rl_initialize): Set
rl_catch_signals to 0 on Win32 platform.
author | Michael Goffioul <michael.goffioul@gmail.com> |
---|---|
date | Tue, 19 Nov 2013 14:21:38 -0500 |
parents | e5566719e0a1 |
children | 1329866151be |
files | libgui/src/thread-manager.cc libinterp/corefcn/sighandlers.cc libinterp/corefcn/sighandlers.h liboctave/util/oct-rl-edit.c |
diffstat | 4 files changed, 177 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/libgui/src/thread-manager.cc +++ b/libgui/src/thread-manager.cc @@ -33,6 +33,7 @@ #include <sys/types.h> #include <signal.h> +#include "sighandlers.h" #include "thread-manager.h" #if defined (__WIN32__) && ! defined (__CYGWIN__) @@ -47,15 +48,7 @@ void interrupt (void) { - // FIXME: This doesn't work when octave_interrupt_immediately is - // true. Octave crashes, presumably in the call to - // octave_jump_to_enclosing_context. Does this happen because the - // jump occurs while Octave is running in the wrong thread? That - // was happening on Unixy systems until we started using - // pthread_kill and blocking interrupts from all threads except the - // one running the Octave interpreter. - - ::raise (SIGINT); + w32_raise_sigint (); } };
--- a/libinterp/corefcn/sighandlers.cc +++ b/libinterp/corefcn/sighandlers.cc @@ -74,6 +74,153 @@ // List of signals we have caught since last call to octave_signal_handler. static bool octave_signals_caught[NSIG]; +// Forward declaration. +static void user_abort (const char *sig_name, int sig_number); + +#if defined (__WIN32__) && ! defined (__CYGWIN__) + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +class +w32_interrupt_manager +{ +public: + ~w32_interrupt_manager (void) + { + if (thread) + CloseHandle (thread); + } + + static bool init (void) { return instance_ok (); } + + static void octave_jump_to_enclosing_context (void) + { + if (instance_ok ()) + instance->do_octave_jump_to_enclosing_context (); + } + + static void user_abort (const char *sig_name, int sig_number) + { + if (instance_ok ()) + instance->do_user_abort (sig_name, sig_number); + } + + static void raise_sigint (void) + { + if (instance_ok ()) + instance->do_raise_sigint (); + } + +private: + w32_interrupt_manager (void) + : thread (0), thread_id (0) + { + thread_id = GetCurrentThreadId (); + + DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), + GetCurrentProcess (), &thread, 0, FALSE, + DUPLICATE_SAME_ACCESS); + } + + static void octave_jump_to_enclosing_context_sync (void) + { +#ifdef _MSC_VER + _fpreset (); +#endif + ::octave_jump_to_enclosing_context (); + } + + void do_octave_jump_to_enclosing_context (void) + { + bool is_interrupt_thread = (GetCurrentThreadId () == thread_id); + + if (is_interrupt_thread) + octave_jump_to_enclosing_context_sync (); + else + { + CONTEXT threadContext; + + SuspendThread (thread); + threadContext.ContextFlags = CONTEXT_CONTROL; + GetThreadContext (thread, &threadContext); + threadContext.Eip = (DWORD) octave_jump_to_enclosing_context_sync; + SetThreadContext (thread, &threadContext); + ResumeThread (thread); + } + } + + void do_user_abort (const char *sig_name, int sig_number) + { + bool is_interrupt_thread = (GetCurrentThreadId () == thread_id); + + if (is_interrupt_thread) + ::user_abort (sig_name, sig_number); + else + { + SuspendThread (thread); + ::user_abort (sig_name, sig_number); + ResumeThread (thread); + } + } + + void do_raise_sigint (void) + { + bool is_interrupt_thread = (GetCurrentThreadId () == thread_id); + + if (is_interrupt_thread) + ::raise (SIGINT); + else + { + SuspendThread (thread); + ::raise (SIGINT); + ResumeThread (thread); + } + } + + static bool instance_ok (void) + { + bool retval = true; + + if (! instance) + { + instance = new w32_interrupt_manager (); + + if (instance) + singleton_cleanup_list::add (cleanup_instance); + } + + if (! instance) + { + ::error ("unable to create w32_interrupt_manager"); + + retval = false; + } + + return retval; + } + + static void cleanup_instance (void) { delete instance; instance = 0; } + +private: + // A handle to the thread that is running the octave interpreter. + HANDLE thread; + + // The ID of the thread that is running the octave interpreter. + DWORD thread_id; + + static w32_interrupt_manager* instance; +}; + +w32_interrupt_manager* w32_interrupt_manager::instance = 0; + +void w32_raise_sigint (void) +{ + w32_interrupt_manager::raise_sigint (); +} + +#endif + // Signal handler return type. #ifndef BADSIG #define BADSIG (void (*)(int))-1 @@ -351,7 +498,11 @@ if (octave_interrupt_state == 0) octave_interrupt_state = 1; +#if defined (__WIN32__) && ! defined (__CYGWIN__) + w32_interrupt_manager::octave_jump_to_enclosing_context (); +#else octave_jump_to_enclosing_context (); +#endif } else { @@ -378,7 +529,11 @@ static void sigint_handler (int sig) { +#if defined (__WIN32__) && ! defined (__CYGWIN__) + w32_interrupt_manager::user_abort (strsignal (sig), sig); +#else user_abort (strsignal (sig), sig); +#endif } #ifdef SIGPIPE @@ -401,6 +556,10 @@ { octave_interrupt_handler retval; +#if defined (__WIN32__) && ! defined (__CYGWIN__) + w32_interrupt_manager::init (); +#endif + #ifdef SIGINT retval.int_handler = octave_set_signal_handler (SIGINT, sigint_handler); #endif @@ -417,6 +576,10 @@ { octave_interrupt_handler retval; +#if defined (__WIN32__) && ! defined (__CYGWIN__) + w32_interrupt_manager::init (); +#endif + #ifdef SIGINT retval.int_handler = octave_set_signal_handler (SIGINT, SIG_IGN); #endif @@ -434,6 +597,10 @@ { octave_interrupt_handler retval; +#if defined (__WIN32__) && ! defined (__CYGWIN__) + w32_interrupt_manager::init (); +#endif + #ifdef SIGINT retval.int_handler = octave_set_signal_handler (SIGINT, h.int_handler, restart_syscalls);
--- a/libinterp/corefcn/sighandlers.h +++ b/libinterp/corefcn/sighandlers.h @@ -82,6 +82,10 @@ octave_set_interrupt_handler (const volatile octave_interrupt_handler&, bool restart_syscalls = true); +#if defined (__WIN32__) && ! defined (__CYGWIN__) +extern OCTINTERP_API void w32_raise_sigint (void); +#endif + // extern void ignore_sigchld (void); // Maybe this should be in a separate file?