/* Signal dispatching thread */ static DWORD WINAPI pg_signal_dispatch_thread(LPVOID param) { HANDLE pipe = (HANDLE) param; BYTE sigNum; DWORD bytes; if (!ReadFile(pipe, &sigNum, 1, &bytes, NULL)) { /* Client died before sending */ CloseHandle(pipe); return 0; } if (bytes != 1) { /* Received <bytes> bytes over signal pipe (should be 1) */ CloseHandle(pipe); return 0; } WriteFile(pipe, &sigNum, 1, &bytes, NULL); /* Don't care if it works or * not.. */ FlushFileBuffers(pipe); DisconnectNamedPipe(pipe); CloseHandle(pipe); pg_queue_signal(sigNum); return 0; }
/* Console control handler will execute on a thread created by the OS at the time of invocation */ static BOOL WINAPI pg_console_handler(DWORD dwCtrlType) { if (dwCtrlType == CTRL_C_EVENT || dwCtrlType == CTRL_BREAK_EVENT || dwCtrlType == CTRL_CLOSE_EVENT || dwCtrlType == CTRL_SHUTDOWN_EVENT) { pg_queue_signal(SIGINT); return TRUE; } return FALSE; }
/* Timer management thread */ static DWORD WINAPI pg_timer_thread(LPVOID param) { DWORD waittime; Assert(param == NULL); waittime = INFINITE; for (;;) { int r; r = WaitForSingleObjectEx(timerCommArea.event, waittime, FALSE); if (r == WAIT_OBJECT_0) { /* Event signalled from main thread, change the timer */ EnterCriticalSection(&timerCommArea.crit_sec); if (timerCommArea.value.it_value.tv_sec == 0 && timerCommArea.value.it_value.tv_usec == 0) waittime = INFINITE; /* Cancel the interrupt */ else { /* WaitForSingleObjectEx() uses milliseconds, round up */ waittime = (timerCommArea.value.it_value.tv_usec + 999) / 1000 + timerCommArea.value.it_value.tv_sec * 1000; } ResetEvent(timerCommArea.event); LeaveCriticalSection(&timerCommArea.crit_sec); } else if (r == WAIT_TIMEOUT) { /* Timeout expired, signal SIGALRM and turn it off */ pg_queue_signal(SIGALRM); waittime = INFINITE; } else { /* Should never happen */ Assert(false); } } return 0; }