1

I am invoking the Set method on an instance of a ManualResetEvent, and it is occasionally deadlocking. I can't find anything in the documentation to indicate that this is a blocking method. What could cause MRE.Set to block?

Stack Trace:

[Managed to Native Transition]
mscorlib.dll!System.Threading.EventWaitHandle.Set() + 0xe bytes
MyCode.StopAll(bool force) Line 179 + 0xd bytes
MyCode.CalcCheckThread() Line 250 + 0xb bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x66 bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x6f bytes
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes



private static void StopAll(bool force)
{
    if( !force )
        LogHelper.SendAllCloseState(logger);

    _forcablyExit = force;
    _running = false;
    _stopWait.Set();  // This line appears to be blocking
}
chilltemp
  • 8,854
  • 8
  • 41
  • 46
  • 2
    What does the code look like?? – MoonKnight Mar 09 '12 at 17:28
  • I added the method that's invoking Set(). I haven't found a pattern in the stack traces of other threads yet. – chilltemp Mar 09 '12 at 17:33
  • This is very odd, as I've never heard/experienced `MRE.Set` to block. Have you tried to put a `Console.WriteLine` or some other output after the call to make sure it's not returning? – Tudor Mar 09 '12 at 17:37
  • No. I'll add additional logging (NLog). This only happens on our servers under full load, so I will not have additional logs today. However, I was able to verify the stack trace by connecting VS2010 to an offending process (was hung since late last night). – chilltemp Mar 09 '12 at 17:54
  • It's a console app that is started/controlled by a windows service. There is no user interaction. It receives Tibco EMS messages that represent work to do, invokes a single threaded calculation engine via a COM dll, then sends the results out via Tibco EMS. – chilltemp Mar 09 '12 at 20:42

1 Answers1

1

We've tracked down the source of this problem with the help of our friends at Microsoft Developer Support.

EventWaitHandle.Set() enters a critical block section, and can be blocked if native code enters a critical block and never releases it. This is happening with a very old 3rd-party library that we are using, and can't be easily replaced/updated.

chilltemp
  • 8,854
  • 8
  • 41
  • 46
  • Wow, no kidding huh? That means you are going to need a fully managed version of `ManualResetEvent`. `ManualResetEventSlim` won't work either since it uses the old MRE behind the scenes. – Brian Gideon Apr 12 '12 at 02:56
  • Try `ManualResetEventSlim` anyway. There are only certain code paths that result in an underlying `ManualResetEvent` getting created. The MRES might just work afterall. – Brian Gideon Apr 12 '12 at 03:08
  • Thanks. Unfortunately, this is 3.5 SP1 and MRES was introduced in 4.0. The MRE is used to notify the main thread that it should finish it's work and exit the app. One such condition is a known state where the native code will never return. Given that this is fatal anyways, we have resorted to signaling the parent app (stdout) that this child app needs to be forcefully terminated (taskkill.exe) if it does not exit on its own within X seconds. Ugly hack, but solves the problem of the day. I'll keep MRES in mind if we upgrade to 4. – chilltemp Apr 13 '12 at 16:01