win32: protect access to ctrlc_flag with critical section.

On Windows, console handlers are run in a separate thread, without
actually interrupting the main thread.
This commit is contained in:
Daniel Beer 2011-09-19 04:33:41 +12:00
parent 9e42c1e6f4
commit b3ffff5945
2 changed files with 40 additions and 6 deletions

View File

@ -32,15 +32,17 @@
#include "util.h" #include "util.h"
#include "output.h" #include "output.h"
static volatile int ctrlc_flag;
#ifdef WIN32 #ifdef WIN32
static int ctrlc_flag;
static HANDLE ctrlc_event; static HANDLE ctrlc_event;
static CRITICAL_SECTION ctrlc_cs;
static WINAPI BOOL ctrlc_handler(DWORD event) static WINAPI BOOL ctrlc_handler(DWORD event)
{ {
if (event == CTRL_C_EVENT) { if (event == CTRL_C_EVENT) {
EnterCriticalSection(&ctrlc_cs);
ctrlc_flag = 1; ctrlc_flag = 1;
LeaveCriticalSection(&ctrlc_cs);
SetEvent(ctrlc_event); SetEvent(ctrlc_event);
return TRUE; return TRUE;
} }
@ -51,12 +53,33 @@ static WINAPI BOOL ctrlc_handler(DWORD event)
void ctrlc_init(void) void ctrlc_init(void)
{ {
ctrlc_event = CreateEvent(0, TRUE, FALSE, NULL); ctrlc_event = CreateEvent(0, TRUE, FALSE, NULL);
InitializeCriticalSection(&ctrlc_cs);
SetConsoleCtrlHandler(ctrlc_handler, TRUE); SetConsoleCtrlHandler(ctrlc_handler, TRUE);
} }
void ctrlc_exit(void)
{
SetConsoleCtrlHandler(NULL, TRUE);
DeleteCriticalSection(&ctrlc_cs);
CloseHandle(ctrlc_event);
}
int ctrlc_check(void)
{
int cc;
EnterCriticalSection(&ctrlc_cs);
cc = ctrlc_flag;
LeaveCriticalSection(&ctrlc_cs);
return cc;
}
void ctrlc_reset(void) void ctrlc_reset(void)
{ {
EnterCriticalSection(&ctrlc_cs);
ctrlc_flag = 0; ctrlc_flag = 0;
LeaveCriticalSection(&ctrlc_cs);
ResetEvent(ctrlc_event); ResetEvent(ctrlc_event);
} }
@ -65,6 +88,8 @@ HANDLE ctrlc_win32_event(void)
return ctrlc_event; return ctrlc_event;
} }
#else /* WIN32 */ #else /* WIN32 */
static volatile int ctrlc_flag;
static void sigint_handler(int signum) static void sigint_handler(int signum)
{ {
ctrlc_flag = 1; ctrlc_flag = 1;
@ -84,16 +109,21 @@ void ctrlc_init(void)
#endif #endif
} }
void ctrlc_exit(void)
{
signal(SIGINT, SIG_DFL);
}
void ctrlc_reset(void) void ctrlc_reset(void)
{ {
ctrlc_flag = 0; ctrlc_flag = 0;
} }
#endif
int ctrlc_check(void) int ctrlc_check(void)
{ {
return ctrlc_flag; return ctrlc_flag;
} }
#endif
char *get_arg(char **text) char *get_arg(char **text)
{ {
@ -310,10 +340,12 @@ char *expand_tilde(const char *path)
if (expanded) if (expanded)
snprintf(expanded, len, "%s%s", home, path + 1); snprintf(expanded, len, "%s%s", home, path + 1);
else else
printc_err("%s: malloc: %s\n", __FUNCTION__, last_error()); printc_err("%s: malloc: %s\n", __FUNCTION__,
last_error());
} else { } else {
printc_err("%s: getenv: %s\n", __FUNCTION__, last_error()); printc_err("%s: getenv: %s\n", __FUNCTION__,
last_error());
} }
} else { } else {
expanded = (char *)malloc(strlen(path) + 1); expanded = (char *)malloc(strlen(path) + 1);
@ -321,7 +353,8 @@ char *expand_tilde(const char *path)
if (expanded) if (expanded)
strcpy(expanded, path); strcpy(expanded, path);
else else
printc_err("%s: malloc: %s\n", __FUNCTION__, last_error()); printc_err("%s: malloc: %s\n", __FUNCTION__,
last_error());
} }
/* Caller must free()! */ /* Caller must free()! */

View File

@ -40,6 +40,7 @@ const char *last_error(void);
/* Check and catch ^C from the user */ /* Check and catch ^C from the user */
void ctrlc_init(void); void ctrlc_init(void);
void ctrlc_exit(void);
void ctrlc_reset(void); void ctrlc_reset(void);
int ctrlc_check(void); int ctrlc_check(void);