Fix sporadic hang in Mono.Debugger.Soft test suite on Windows.
authorlateralusX <lateralusx.github@gmail.com>
Wed, 23 Aug 2017 08:38:56 +0000 (10:38 +0200)
committerlateralusX <lateralusx.github@gmail.com>
Mon, 25 Sep 2017 13:41:32 +0000 (15:41 +0200)
commit76640001ebd9d400a59c78cf98d29c4616f6fd2e
treedaeb4046e8a8ec14ce0b0475ba34b02a53e81d43
parent878b260edc6eefc7ec36244f8a30af6aa475fcf8
Fix sporadic hang in Mono.Debugger.Soft test suite on Windows.

Mono.Debugger.Soft has low frequency hangs in InspectThreadSuspenedOnWaitOne test.
This method launch the debuggee (dtest-app.exe), sets a breakpoint on a method just
doing an infinite OS wait, validate that the breakpoint gets hit and resumes debuggee.
After resume from breakpoint debuggee will hit the infinite OS wait and the debugger test
will suspend and shutdown the process.

In order for mono debugger to handle the shutdown request it will suspend all managed threads
using mono_thread_suspend_all_other_threads. This method uses a pooling schema until all threads
have reported that they are suspended. Since one of the threads are doing an infinite OS wait we
entered the land of APC (Asynchron Procedure Calls) used on Windows to alert waitable threads.

The reason for the hang is the fact that the OS won’t return from the wait until all queued APC’s
have been executed. Since the loop sending async suspend requests to the
threads mono_thread_suspend_all_other_threads can run faster (including suspending/resuming the
thread that need to consume APC’s in the process) then the dequeue and execute of the queued APC’s, the
wait won’t break, meaning that the thread won’t be able to set the mono suspend state causing the
mono_thread_suspend_all_other_threads to run forever. This is highly timing dependent and will only reproduce
sporadic, but I was able to isolate and do a solid repro locally while working on the fix.

The fix makes sure we don’t post a new suspend APC if there is already one in flight with a pending unhandled
interruption. This will make sure we won’t flood the APC queue on Windows preventing the thread from suspending.
14 files changed:
mono/metadata/gc.c
mono/metadata/monitor.c
mono/metadata/threadpool.c
mono/metadata/threads.c
mono/metadata/w32socket-win32.c
mono/utils/Makefile.am
mono/utils/mono-os-semaphore.h
mono/utils/mono-os-wait-win32.c [new file with mode: 0644]
mono/utils/mono-os-wait.h [new file with mode: 0644]
mono/utils/mono-threads-windows.c
mono/utils/mono-threads.h
mono/utils/os-event-win32.c
msvc/libmonoutils.vcxproj
msvc/libmonoutils.vcxproj.filters