diff options
-rw-r--r-- | asmrun/signals.c | 6 | ||||
-rw-r--r-- | byterun/signals.c | 6 | ||||
-rw-r--r-- | byterun/win32.c | 47 |
3 files changed, 59 insertions, 0 deletions
diff --git a/asmrun/signals.c b/asmrun/signals.c index 158558a88..1d855f343 100644 --- a/asmrun/signals.c +++ b/asmrun/signals.c @@ -31,6 +31,12 @@ #include <sys/resource.h> #endif +#ifdef _WIN32 +typedef void (*sighandler)(int sig); +extern sighandler win32_signal(int sig, sighandler action); +#define signal(sig,act) win32_signal(sig,act) +#endif + #if defined(TARGET_power) && defined(SYS_rhapsody) /* Confer machdep/ppc/unix_signal.c and mach/ppc/thread_status.h in the Darwin sources */ diff --git a/byterun/signals.c b/byterun/signals.c index e376237ab..25920a9ed 100644 --- a/byterun/signals.c +++ b/byterun/signals.c @@ -28,6 +28,12 @@ #include "rotatecursor.h" #endif /* macintosh */ +#ifdef _WIN32 +typedef void (*sighandler)(int sig); +extern sighandler win32_signal(int sig, sighandler action); +#define signal(sig,act) win32_signal(sig,act) +#endif + int volatile async_signal_mode = 0; int volatile pending_signal = 0; int volatile something_to_do = 0; diff --git a/byterun/win32.c b/byterun/win32.c index 44eb2bec8..bd82ca699 100644 --- a/byterun/win32.c +++ b/byterun/win32.c @@ -140,6 +140,53 @@ char * caml_dlerror(void) return dlerror_buffer; } +/* Proper emulation of signal(), including ctrl-C and ctrl-break */ + +typedef void (*sighandler)(int sig); +static int ctrl_handler_installed = 0; +static volatile sighandler ctrl_handler_action = SIG_DFL; + +static BOOL WINAPI ctrl_handler(DWORD event) +{ + int saved_mode; + sighandler action; + + /* Only ctrl-C and ctrl-Break are handled */ + if (event != CTRL_C_EVENT && event != CTRL_BREAK_EVENT) return FALSE; + /* Default behavior is to exit, which we get by not handling the event */ + if (ctrl_handler_action == SIG_DFL) return FALSE; + /* Ignore behavior is to do nothing, which we get by claiming that we + have handled the event */ + if (ctrl_handler_action == SIG_IGN) return TRUE; + /* Reset handler to default action for consistency with signal() */ + action = ctrl_handler_action; + ctrl_handler_action = SIG_DFL; + /* Call user-provided signal handler. Win32 doesn't like it when + we do a longjmp() at this point (it looks like we're running in + a different thread than the main program!). So, pretend we are not in + async signal mode, so that the handler simply records the signal. */ + saved_mode = async_signal_mode; + async_signal_mode = 0; + action(SIGINT); + async_signal_mode = saved_mode; + /* We have handled the event */ + return TRUE; +} + +sighandler win32_signal(int sig, sighandler action) +{ + sighandler oldaction; + + if (sig != SIGINT) return signal(sig, action); + if (! ctrl_handler_installed) { + SetConsoleCtrlHandler(ctrl_handler, TRUE); + ctrl_handler_installed = 1; + } + oldaction = ctrl_handler_action; + ctrl_handler_action = action; + return oldaction; +} + /* Expansion of @responsefile and *? file patterns in the command line */ #ifndef HAS_UI |