windows: Better handling of Ctrl-C
This builds upon the changes made in 2195046365c. 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.
This commit is contained in:
parent
1b7f622410
commit
a5aa03acaf
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user