Bug 883 - Monitor.Wait return false immediately on Mono Runtime
Summary: Monitor.Wait return false immediately on Mono Runtime
Status: RESOLVED FIXED
Alias: None
Product: Runtime
Classification: Mono
Component: io-layer ()
Version: unspecified
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2011-09-18 14:19 UTC by sabro
Modified: 2015-11-19 16:48 UTC (History)
5 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description sabro 2011-09-18 14:19:57 UTC
I am using Monodevelop on Windows Vista.

I build a following code by .NET Runtime. 
Then, 'True' is displayed in 3 second later.

Next, I build by mono2.10.5 runtime.
And I execute it. But 'False' is displayed in console immediately.

Monitor.Wait should wait until other thread send pulse
And Monitor.Wait should return 'True' before 10 second past.



using System;
using System.Threading;

namespace MonoThreadTest
{
  class MainClass
  {
    static object lockObj = new object();
    
    public static void Main (string[] args)
    {
      new Thread(new ThreadStart(Async)).Start();
      
      Thread.Sleep(3 * 1000);
      
      lock(lockObj)
      {
        Monitor.PulseAll(lockObj);
      }
      
      Console.Read();
    }
    
    static void Async()
    {
      lock(lockObj)
      {
        Console.WriteLine(Monitor.Wait(lockObj, 10 * 1000));
      }
    }
  }
}
Comment 1 Zoltan Varga 2011-09-22 21:39:41 UTC
This works-for-me on linux using either HEAD or 2.10.
Comment 2 sabro 2011-09-22 21:56:40 UTC
I think this issue occur on windows only.
Because Monitor class use win32 api.
Comment 3 Zoltan Varga 2011-09-27 16:20:21 UTC
I can't reproduce with 2.10.2 on windows 7 x64 either.
Comment 4 sabro 2011-10-17 03:15:18 UTC
I find out one new things.
That code return false in debug run.
But it return true in normal run.
Comment 5 Philip Norton 2013-04-03 12:30:52 UTC
Looks like this is caused by the QueueUserAPC call in debugger-agent.c:2529, which happens only on Windows.
This call causes all threads in an alertable wait state to return immediately with WAIT_IO_COMPLETION.  That's why Sleeps, Monitors, locks, etc all act crazy when debugging on Windows.
I can remove this QueueUserAPC call, and it works correctly as long as breakpoints aren't set, in which case the debugger hangs.  I'm new to this whole codebase, does anybody have any ideas where I should look next?
Comment 6 Zoltan Varga 2013-04-03 12:35:19 UTC
We use that call to suspend threads, the apc checks whenever we are in managed code or not. If we are in managed code, we suspend, if we are not, we let the thread continue. So it cannot be removed.
Comment 7 Philip Norton 2013-04-08 12:15:57 UTC
I have submitted a patch which resolves this problem, and a few other related ones. Turns out that Semaphores, WaitHandle.*, and Thread.Join also had the same problem.  Monitor.Enter/TryEnter was working fine.
The fix was to make sure that after a WaitForSingleObjectEx/WaitForMultipleObjectsEx is interrupted by QueueUserAPC, to re-enter the wait, after calculating the elapsed time and updating the timeout.