Workaround for VS2013 - Workaround for cl.exe deadlock for VS2013. In wine environment, cl.exe sometimes tries to call EnterCriticalSection with zero-cleared CRITICAL_SECTION. Wine thinks it so that someone has already taken a lock, so cl.exe is stopped to wait for lock which no one holds. If someone has taken a lock, RecursionCount should be 1. So zero-cleared CriticalSection should mean no one holds a lock now. Thus, it should be OK to allow cl.exe to enter a critical section for workaround. - cl.exe for VS2013 sometimes cannot find headers. For example, 'C:\foo1.h': can be found 'C:\foo12.h' : cannot be found 'C:\foo123.h' : can be found. When long_nameW is copied with memcpy to filename, wine sometimes copy garbage characters. So, cl.exe tried finding 'C:\foo1.hh', 'C:\foo123.hi' or something. In this workaround, we initialize long_nameW with zero. Change-Id: Ie2ddafa01920a298d046d0f98b860f3ff0f7a25c
diff --git a/dlls/ntdll/critsection.c b/dlls/ntdll/critsection.c index d374916..3abc9b4 100644 --- a/dlls/ntdll/critsection.c +++ b/dlls/ntdll/critsection.c
@@ -507,6 +507,18 @@ return ret; } +static BOOL IsAllZero(const void* begin, size_t size) +{ + const char* m = begin; + int i; + + for (i = 0; i < size; ++i) { + if (m[i] != 0) + return FALSE; + } + + return TRUE; +} /*********************************************************************** * RtlEnterCriticalSection (NTDLL.@) @@ -527,6 +539,25 @@ */ NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit ) { + // VS2013 cl.exe calls this with zero cleared crit. + // As far as we examined, this does not happen in real Windows. + // So maybe there is a wine bug that causes this. However, I have no idea + // about what causes this. + // Let's allow it to enter critical section for workaround. + if (IsAllZero(crit, sizeof(RTL_CRITICAL_SECTION))) { + if (interlocked_cmpxchg(&crit->SpinCount, 4000, 0) == 0) { + // OK. SpinCount was 0, and now 4000. + crit->LockCount = -1; + } + + // When interlocked_cmpxchg was failed, someone changed SpinCount + // after IsAllZero(). With this workaround, someone will change or + // has changed crit->LockCount to -1. Leaving LockCount as is so that + // this thread (or the other thread) will wait for lock release. + // In usual case, cl.exe will return critical section with zero-cleared + // crit only once. So this shouldn't happen, though. + } + if (crit->SpinCount) { ULONG count;
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c index cd2ee90..eeff643 100644 --- a/dlls/ntdll/directory.c +++ b/dlls/ntdll/directory.c
@@ -1255,7 +1255,7 @@ union file_directory_info *info; int i, long_len, short_len, total_len; struct stat st; - WCHAR long_nameW[MAX_DIR_ENTRY_LEN]; + WCHAR long_nameW[MAX_DIR_ENTRY_LEN] = { (WCHAR)0 }; WCHAR short_nameW[12]; WCHAR *filename; UNICODE_STRING str;