Race conditions in critical.c?

Fawzi Mohamed fmohamed at mac.com
Thu Sep 25 23:19:00 PDT 2008


On 2008-09-25 23:23:10 +0200, Mike Hearn  <mike at plan99.net> said:

> Sorry, hit return too early. So is anybody going to take a look at 
> this? I just noticed there is a Bugzilla, should I file a bug?

You are right dcs->next should be set only after the initialization is 
performed.
do submit a bug on bugzilla
	http://d.puremagic.com/issues/

Well spotted!

Fawzi
> 
> Mike Hearn  Wrote:
> 
>> Mike Hearn Wrote:
>> 
>>> I was reading the code to the phobos runtime library and saw the 
>>> following code in critical.c:
>>> 
>>> void _d_criticalenter(D_CRITICAL_SECTION *dcs)
>>> {
>>> if (!dcs->next)
>>> {
>>> EnterCriticalSection(&critical_section.cs);
>>> if (!dcs->next) // if, in the meantime, another thread didn't set it
>>> {
>>> dcs->next = dcs_list;
>>> <----
>>> dcs_list = dcs;
>>> InitializeCriticalSection(&dcs->cs);
>>> }
>>> LeaveCriticalSection(&critical_section.cs);
>>> }
>>> EnterCriticalSection(&dcs->cs);
>>> }
>>> 
>>> There's a race condition here - consider a thread that is suspended at 
>>> the marked point. Another thread then attempts to lock the critsec. It 
>>> sees that dcs->next is set and calls EnterCriticalSection on an 
>>> uninitialized CRITICAL_SECTION.
>>> 
>>> The Linux code has the same problem, and then another one as well - the 
>>> initialization of the "critsec lock" is itself lazy and is not 
>>> protected by anything at all. The result is potentially multiple 
>>> initializations of that lock, and because atexit does not coalesce 
>>> multiple registrations, a potentially catastrophic multiple invocation 
>>> of _STD_critical_term.
>>> 
>>> It appears this code (for both platforms) needs to be scrapped and 
>>> rewritten. I'd start by checking that lazy initialization of critsecs 
>>> is actually needed - do D compilers really generate tons of potentially 
>>> unnecessary D_CRITICAL_SECTIONs?
>>> 
>>> thanks -mike





More information about the Digitalmars-d mailing list