Commit a5aa03ac authored by stijn's avatar stijn Committed by Paul Sokolovsky
Browse files

windows: Better handling of Ctrl-C

This builds upon the changes made in 21950463. Using signal() does not
produce reliable results so SetConsoleCtrlHandler is used, and the handler
is installed only once during initialization instead of removing it in
mp_hal_set_interrupt_char when it is not strictly needed anymore, since
removing it might lead to Ctrl-C events being missed because they are
fired on a seperate thread which might only become alive after the handler
was removed.
parent 1b7f6224
......@@ -26,9 +26,13 @@
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
#include "sleep.h"
extern BOOL WINAPI console_sighandler(DWORD evt);
void init() {
SetConsoleCtrlHandler(console_sighandler, TRUE);
init_sleep();
#ifdef __MINGW32__
putenv("PRINTF_EXPONENT_DIGITS=2");
......@@ -40,5 +44,6 @@ void init() {
}
void deinit() {
SetConsoleCtrlHandler(console_sighandler, FALSE);
deinit_sleep();
}
......@@ -30,7 +30,6 @@
#include <windows.h>
#include <unistd.h>
#include <signal.h>
HANDLE std_in = NULL;
HANDLE con_out = NULL;
......@@ -67,15 +66,27 @@ void mp_hal_stdio_mode_orig(void) {
SetConsoleMode(std_in, orig_mode);
}
STATIC void sighandler(int signum) {
if (signum == SIGINT) {
// Handler to be installed by SetConsoleCtrlHandler, currently used only to handle Ctrl-C.
// This handler has to be installed just once (this has to be done elswhere in init code).
// Previous versions of the mp_hal code would install a handler whenever Ctrl-C input is
// allowed and remove the handler again when it is not. That is not necessary though (1),
// and it might introduce problems (2) because console notifications are delivered to the
// application in a seperate thread.
// (1) mp_hal_set_interrupt_char effectively enables/disables processing of Ctrl-C via the
// ENABLE_PROCESSED_INPUT flag so in raw mode console_sighandler won't be called.
// (2) if mp_hal_set_interrupt_char would remove the handler while Ctrl-C was issued earlier,
// the thread created for handling it might not be running yet so we'd miss the notification.
BOOL WINAPI console_sighandler(DWORD evt) {
if (evt == CTRL_C_EVENT) {
if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) {
// this is the second time we are called, so die straight away
exit(1);
}
mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj);
return TRUE;
}
return FALSE;
}
void mp_hal_set_interrupt_char(char c) {
......@@ -85,13 +96,11 @@ void mp_hal_set_interrupt_char(char c) {
GetConsoleMode(std_in, &mode);
mode |= ENABLE_PROCESSED_INPUT;
SetConsoleMode(std_in, mode);
signal(SIGINT, sighandler);
} else {
DWORD mode;
GetConsoleMode(std_in, &mode);
mode &= ~ENABLE_PROCESSED_INPUT;
SetConsoleMode(std_in, mode);
signal(SIGINT, SIG_DFL);
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment