diff --git a/windows/init.c b/windows/init.c
index 5e96af046eedc9e0f3e0e9bf12bae5ff33dafc67..d4533f9b478009dbc269a201078883cfdffd5cbc 100644
--- a/windows/init.c
+++ b/windows/init.c
@@ -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();
 }
diff --git a/windows/windows_mphal.c b/windows/windows_mphal.c
index 91025d6cf46cbb6b79b583dbcfa9d78def2af513..6cc4f65428cd2684115f5520e2ffd0e78e4da879 100644
--- a/windows/windows_mphal.c
+++ b/windows/windows_mphal.c
@@ -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);
     }
 }