Bug 11598 - SemaphoreSlim.Wait uses 100% CPU
Summary: SemaphoreSlim.Wait uses 100% CPU
Status: NEW
Alias: None
Product: Class Libraries
Classification: Mono
Component: System (show other bugs)
Version: master
Hardware: PC Linux
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2013-04-04 19:21 UTC by Weeble
Modified: 2013-11-16 21:20 UTC (History)
2 users (show)

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


Attachments

Description Weeble 2013-04-04 19:21:16 UTC
Summary:

Waiting on a SemaphoreSlim that was initialized with an initialCount of 0 and has not yet been released will use 100% CPU on one core.

Reproduction:

This example program will pause for 10 seconds with 100% CPU usage:

    using System.Threading;
    
    public static class Program
    {
        public static void Main(string[] args)
        {
            var sem = new SemaphoreSlim(0);
            sem.Wait(10000);
        }
    }

Expected behaviour would be to pause for 10 seconds with negligible CPU usage.

This similar program will indeed pause for 10 seconds with negligible CPU usage:

    public static class Program
    {
        public static void Main(string[] args)
        {
            var sem = new SemaphoreSlim(0);
            sem.Release();
            sem.Wait();
            sem.Wait(10000);
        }
    }

I've observed this behaviour on Linux with Mono 2.8.10 and 3.0.1. I've observed it on OSX, but I'll need to check the Mono version number.

Analysis:

I believe this is a bug in SemaphoreSlim's constructor:

https://github.com/mono/mono/blob/master/mcs/class/corlib/System.Threading/SemaphoreSlim.cs#L57

    this.handle = new ManualResetEvent (initialCount == 0);

The event is initialized to be signalled if initialCount is 0 and not signalled if initialCount is greater than 0. This seems to be the wrong way round. If initialCount is 0 then a Wait cannot succeed and so the event should not be signalled. This means that the Wait spins furiously because every time it tries to block to wait for the event it finds that the event is signalled, but every time it checks to see if the semaphore's count is positive it finds that it isn't and decides to try to wait again.

After the semaphore has been released at least once, the event's state becomes consistent with the counter, so this only happens before the first release.
Comment 2 Weeble 2013-11-16 21:20:31 UTC
Can this be marked resolved? I think the fix is good, but it's still marked 'new'.

Note You need to log in before you can comment on or make changes to this bug.