diff options
author | Simon Marlow <simonmar@microsoft.com> | 2006-03-20 16:34:39 +0000 |
---|---|---|
committer | Simon Marlow <simonmar@microsoft.com> | 2006-03-20 16:34:39 +0000 |
commit | afe67cb590a9bc1adb729e0757fd698ff10d4492 (patch) | |
tree | 05639aecc2723de8180254ed07602af30f01b0a4 /ghc/rts | |
parent | 1f5e3b2472084434edf71a89c4764d1509e8e9b0 (diff) | |
download | haskell-afe67cb590a9bc1adb729e0757fd698ff10d4492.tar.gz |
stopTicker(): wait for the timer thread to exit
Diffstat (limited to 'ghc/rts')
-rw-r--r-- | ghc/rts/win32/Ticker.c | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/ghc/rts/win32/Ticker.c b/ghc/rts/win32/Ticker.c index c1390b7d76..0923fea5f0 100644 --- a/ghc/rts/win32/Ticker.c +++ b/ghc/rts/win32/Ticker.c @@ -8,6 +8,7 @@ #include <windows.h> #include <stdio.h> #include <process.h> +#include "OSThreads.h" /* * Provide a timer service for the RTS, periodically @@ -20,6 +21,7 @@ * signals.) */ static HANDLE hStopEvent = INVALID_HANDLE_VALUE; +static HANDLE tickThread = INVALID_HANDLE_VALUE; static TickProc tickProc = NULL; @@ -38,11 +40,13 @@ unsigned WINAPI TimerProc(PVOID param) { + return 0; + int ms = (int)param; DWORD waitRes; - /* interpret a < 0 timeout period as 'instantaneous' */ - if (ms < 0) ms = 0; + /* interpret a < 0 timeout period as 'instantaneous' */ + if (ms < 0) ms = 0; while (1) { waitRes = WaitForSingleObject(hStopEvent, ms); @@ -86,19 +90,37 @@ startTicker(nat ms, TickProc handle_tick) return 0; } tickProc = handle_tick; - return ( 0 != _beginthreadex(NULL, + tickThread = (HANDLE)(long)_beginthreadex( NULL, 0, TimerProc, (LPVOID)ms, 0, - &threadId) ); + &threadId); + return (tickThread != 0); } int stopTicker(void) { - if (hStopEvent != INVALID_HANDLE_VALUE) { - SetEvent(hStopEvent); - } - return 0; + // We must wait for the ticker thread to terminate, since if we + // are in a DLL that is about to be unloaded, the ticker thread + // cannot be allowed to return to a missing DLL. + + if (hStopEvent != INVALID_HANDLE_VALUE && + tickThread != INVALID_HANDLE_VALUE) { + DWORD exitCode; + SetEvent(hStopEvent); + while (1) { + WaitForSingleObject(tickThread, 20); + if (!GetExitCodeThread(tickThread, &exitCode)) { + return 1; + } + if (exitCode != STILL_ACTIVE) { + tickThread = INVALID_HANDLE_VALUE; + return 0; + } + TerminateThread(tickThread, 0); + } + } + return 0; } |