#3748: Bug in rts/Win32/Ticker.c can cause process hang on exit in Win32
---------------------------------+------------------------------------------
Reporter: sgf | Owner:
Type: bug | Status: new
Priority: normal | Component: Runtime System
Version: 6.10.4 | Keywords:
Os: Windows | Testcase:
Architecture: Unknown/Multiple | Failure: Runtime crash
---------------------------------+------------------------------------------
On Win32, the ticker thread is shut down by signalling for it to close,
waiting 20ms, and then calling !TerminateThread if it hasn't already
terminated. On a heavily-loaded system, the 20ms timeout can be exceeded,
and !TerminateThread is called. There is then a race condition. According
to our tests, in about 1 in 100 calls to !TerminateThread, the ticker
thread is holding the Windows loader lock (which is held during parts of
thread shutdown). It is killed holding the lock, and no other thread can
acquire the lock. Therefore, no other thread can die, and the whole
process hangs on exit.
Isn't the Win32 API lovely?
Given the timeout occurs about 1 in 100 times on a heavily-loaded box
(more runnable threads than cores), and then the hang occurs on 1 in 100
timeouts, it's a slightly tedious bug to reproduce. My test case was 4
shell windows in infinite loops running a small GHC executable that forces
the ticker thread to be started by using System.Timeout.timeout.
My suggestions:
As the code suggests, if the ticker is compiled into a DLL, the thread
must die before the DLL can be safely unloaded - otherwise an unhandled
exception will wreak havoc in the process. The best suggestion I can think
of is to increase the timeout, to 200ms say. After all, the timeout should
rarely be reached except on heavily loaded systems, few people need a
guaranteed quick response time on DLL unload, and any time the timeout is
hit we introduce the possibility of basically breaking the process when we
call !TerminateThread.
For the runtime compiled into an executable, there is no need to call
!TerminateThread. The executable will remain mapped until after the ticker
thread is forcibly terminated by the Windows system. Instead, we can
simply attempt to signal the thread to close, wait for a timeout, and then
shrug our shoulders and return, giving the least-unclean program shutdown
possible in that case.
If people are happy with my proposed changes, I can make a patch.
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/3748>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs