[Mono-bugs] [Bug 557212] New: .Net Remoting TCP server channel subject to race condition

bugzilla_noreply at novell.com bugzilla_noreply at novell.com
Fri Nov 20 08:30:33 EST 2009



           Summary: .Net Remoting TCP server channel subject to race
    Classification: Mono
           Product: Mono: Class Libraries
           Version: 2.4.x
          Platform: x86
        OS/Version: Linux
            Status: NEW
          Severity: Normal
          Priority: P5 - None
         Component: System
        AssignedTo: mono-bugs at lists.ximian.com
        ReportedBy: sgroot at tkl.iis.u-tokyo.ac.jp
         QAContact: mono-bugs at lists.ximian.com
          Found By: ---
           Blocker: ---

User-Agent:       Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64;
Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729;
Media Center PC 6.0; InfoPath.3; Creative AutoUpdate v1.40.01; Creative
AutoUpdate v1.40.03)

The System.Runtime.Remoting.Channels.RemotingThreadPool class
(System.Runtime.Remoting assembly), which is used by the TCP channel to handle
incoming connections, is subject to a race condition.

The freeThreads field is incremented by the PoolThread function, and it is
decremented by the RunThread function. The following race condition can occur,
causing the freeThreads field to be updated incorrectly:

1. More than one thread is waiting (freeThreads is larger than 1).
2. One the pool threads' time outs expires, but that thread does not yet run.
3. RunThread is called, which decrements freeThreads and calls Monitor.Pulse.
4. Monitor.Pulse adds a thread to the ready queue.
5. The timed out thread runs first, and gets the work item.
6. When the timed out thread finishes, it increments freeThreads and waits
7. The pulsed thread runs, but doesn't get the work item. It increments
freeThreads and waits again.

This problem occurs because RunThread assumes that Monitor.Pulse will wake at
most one thread, which is true. However, because the PoolThread function will
check the queue even when Monitor.Wait timed out, more than one thread can be
waiting to run when Monitor.Pulse is called. When a timed out thread gets the
work item, freeThreads isn't decremented for that thread.

Note that it also isn't safe to just decrement freeThreads if Monitor.Wait
timed out. This would lead to problems if Monitor.Pulse didn't signal any
threads (which is possible if all running threads have timed out) in which case
freeThreads would be decremented too often, which isn't an option.

The only safe way to deal with this is to decrement freeThreads *only* in
PoolThread, not in RunThread. This would however mean that multiple calls to
RunThread can queue up more items than there are free threads because that
value hadn't been decremented yet. There are ways to circumvent this as well
but they are not trivial.

The RemotingThreadPool is a weak point of the whole TCP channel infrastructure
(see also my bug 474217). I would suggest rearchitecting this entirely.

Reproducible: Sometimes

Steps to Reproduce:
Not applicable. It's a race condition, it'll either happen or it won't.
Actual Results:  
The RemotingThreadPool has a race condition that can cause a delay on the
processing of work items as it will think there are more free threads than
there actually are.

Expected Results:  
I expected the RemotingThreadPool to not have a race condition.

Configure bugmail: http://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.

More information about the mono-bugs mailing list