This mail is about bugs 28042[1] and 28677[2]. In short, what I'm trying to deal with is buggy applications that make calls to DSound and WinMM from within DllMain(), causing deadlocks.
On almost any entry into DSound or WinMM's wave functions, the modules launch a thread to communicate with MMDevAPI. We create a new thread for two reasons. First, to CoInitialize() the thread, which we shouldn't do on a user thread. Second, the MMDevAPI docs say that the device objects should be created and destroyed from the same thread[3], which we can't guarantee if we create them on a user thread (I think dsound currently violates this, actually).
Wine holds the loader critical section during calls to DllMain(). However, launching a new thread requires using the loader, and so we hit a deadlock. This is the problem reported by these bugs.
While we might be able to perform some of these functions without launching a new thread, I'm not sure that that's a general solution, since we will have to launch a thread at some point. Analysis on Windows 7 shows that DirectSoundEnumerate() does not launch any additional threads, but mixerGetNumDevs() actually does launch a thread, yet the application still launches successfully.
So, I'm asking for insights. Should I try hard to avoid launching threads unless absolutely necessary? Is this a known deficiency in the loader, and I should do nothing? Is there some other way to work around this?
Thanks, Andrew
[1] http://bugs.winehq.org/show_bug.cgi?id=28042 [2] http://bugs.winehq.org/show_bug.cgi?id=28677 [3] http://msdn.microsoft.com/en-us/library/windows/desktop/dd370873%28v=VS.85%2...
Andrew Eikum aeikum@codeweavers.com wrote:
So, I'm asking for insights. Should I try hard to avoid launching threads unless absolutely necessary? Is this a known deficiency in the loader, and I should do nothing? Is there some other way to work around this?
As usually first thing to do is to write some tests and investigate what Windows does/how it copes with such cases.
On Wed, Jan 11, 2012 at 01:03:56AM +0800, Dmitry Timoshkov wrote:
Andrew Eikum aeikum@codeweavers.com wrote:
So, I'm asking for insights. Should I try hard to avoid launching threads unless absolutely necessary? Is this a known deficiency in the loader, and I should do nothing? Is there some other way to work around this?
As usually first thing to do is to write some tests and investigate what Windows does/how it copes with such cases.
Some more testing just confirms that we should be able to launch threads from within a client DllMain(). I wrote a test DLL, compiled in MSVC++ 2010, which basically does (pseudocode, obviously):
DllMain(){ winmm = LoadLibrary("WinMM.dll"); wOGND = GetProcAddress(winmm, "waveOutGetNumDevs"); printf("%u\n", wOGND()); }
I then load that DLL from a (severely hacked) dsound_crosstest.exe, which does not link against dsound or winmm.
Printing the result from waveOutGetNumDevs() shows that it works (it returns 2, which is correct). Monitoring the thread count via Task Manager before and after the call shows that waveOutGetNumDevs() launches a thread, like I mentioned in the first email.
Running that dsound test in Wine to load dmtest.dll deadlocks waiting for the loader CS, just like the bugs linked in the first email.
So it appears we should be able to launch threads in DllMain() without deadlocking.
Thoughts, anyone?
Andrew
On 10 January 2012 20:55, Andrew Eikum aeikum@codeweavers.com wrote:
So it appears we should be able to launch threads in DllMain() without deadlocking.
Thoughts, anyone?
That should be easy enough to test. Is the issue just launching a thread though, or actually waiting for it to start?
On Tue, Jan 10, 2012 at 09:10:15PM +0100, Henri Verbeet wrote:
On 10 January 2012 20:55, Andrew Eikum aeikum@codeweavers.com wrote:
So it appears we should be able to launch threads in DllMain() without deadlocking.
Thoughts, anyone?
That should be easy enough to test. Is the issue just launching a thread though, or actually waiting for it to start?
You're right. I jumped to the conclusion that they were using that thread to complete the GetNumDevs() call. If I explicitly spawn a thread and wait for it in dmtest.dll, it deadlocks on Windows as well. So that's the wrong answer.