EnterCriticalSection throws exception?

Huang, Zhangrong hzhrong at gmail.com
Wed Jul 2 12:06:41 CDT 2008


Hi,

According to MSDN  http://msdn.microsoft.com/en-us/library/ms682608(VS.85).aspx:

EnterCriticalSection can raise EXCEPTION_POSSIBLE_DEADLOCK if a wait
operation on the critical section times out. The timeout interval is
specified by the following registry value:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
Manager\CriticalSectionTimeout.

Currently, WIne doesn't implement this timeout feature, instead wine
throws exception only for Wine internal locks after waiting for about
65 seconds, it is useful to check deadlock, see
RtlpWaitForCriticalSection in dlls/ntdll/critsection.c

But this means a thread can't hold critical section longer than 65
seconds, otherwise app will crash. On some conditions, a thread does
need hold critical section more than 65 seconds, for example: wine's
implementation of GetAddress uses a critical section to protect
non-reentrant gethostbyname() (well maybe need another
gethostbyname_r() patch),  see dlls/wininet/utility.c
As you can see, gethostbyname() may take longtime when DNS setting is
wrong or network is broken. If a multi-thread app calls GetAddress
simultaneous in many threads, the app will crash.

I meet this problem when my network was broken, my app kept crash:

fixme:wininet:InternetSetOptionW INTERNET_OPTION_SEND/RECEIVE_TIMEOUT
err:ntdll:RtlpWaitForCriticalSection section 0x7e44fa80 "utility.c:
cs_gethostbyname" wait timed out in thread 0037, blocked by 003b,
retrying (60 sec)
fixme:msxml:DllCanUnloadNow
wine: Critical section 7e44fa80 wait failed at address 0x7bc3c5bc
(thread 0039), starting debugger...
WineDbg starting on pid 0008
Unhandled exception: wait failed on critical section 0x7e44fa80 cs_gethostbyname
err:seh:raise_exception Unhandled exception code c0000194 flags 0 addr
0x7bc3c5bc

So I suggest a feature that EnterCriticalSection throws exception for
Wine internal locks only when debug is present.

Add the following code dlls/ntdll/critsection.c:

NTSTATUS WINAPI RtlpWaitForCriticalSection( RTL_CRITICAL_SECTION *crit )
{
...........................
        /* Throw exception only for Wine internal locks and debug is present */
        if ((!crit->DebugInfo) || (!crit->DebugInfo->Spare[0])) continue;
        else if (!NtCurrentTeb()->Peb->BeingDebugged) continue;
        ^^^^^^^^^^^^^^^^^^ add ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

        rec.ExceptionCode    = STATUS_POSSIBLE_DEADLOCK;
............................
}

Any suggestion? Sorry If I'm not clean or missing something, thanks.

-- 
$ apt-get moo
 (__)
 (oo)
 /------\/
 / | ||
 * /\---/\
 ~~ ~~
...."Have you mooed today?"...



More information about the wine-devel mailing list