http://bugs.winehq.org/show_bug.cgi?id=11582
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |focht@gmx.net
--- Comment #8 from Anastasius Focht focht@gmx.net 2010-06-13 06:30:49 --- Hello,
looks like combination of Wine bug and incredibly stupid app code in some pathetic software protection scheme.
tid 24 = main thread tid 26 = debugger thread
--- snip --- 0024:Call user32.CreateWindowExA(00000080,00439f0c "Turnkexe951396Flash.exe",0045176c "ReleaseNow.com Turnkey Technology",02cf0000,000002e4,00000208,000000c8,00000014,00000000,00000000,00400000,00000000) ret=00406f7f ... 0024:Ret user32.CreateWindowExA() retval=000501a0 ret=00406f7f. ... 0024:Call KERNEL32.CreateThread(00000000,00000000,004018f0,00000000,00000000,0032aae0) ret=00401e81 0024:Ret KERNEL32.CreateThread() retval=00000054 ret=00401e81 0024:Call KERNEL32.Sleep(00001388) ret=00401e91 ... 0026:Starting thread proc 0x4018f0 (arg=(nil)) 0026:Call user32.ShowWindow(000501a0,00000000) ret=00401944 0024:Ret KERNEL32.Sleep() retval=00000000 ret=00401e91 <thread 0024 live locks here, eating 100% CPU> --- snip ---
To understand the problem, I present relevant pseudo code snippets of both threads, made up from disassembly.
Comments are courtesy of http://stackoverflow.com/questions/184618/what-is-the-best-comment-in-source... - I picked some to spice this stupid code up ;-)
--- snip main app thread ---
... /* reset global variable */ process_info.handle = 0; ... /* please work */ thread = CreateThread(0, 0, debugger_thread_proc, 0, 0, &tid); /* these magic numbers are fscking stupid. */ Sleep( 0x1388); /* please god, when will the hurting stop? */ while ( !process_info.handle) ; WaitForInputIdle( process_info.handle, 0x1388); ... --- snip main app thread ---
--- snip debugger thread --- ... ShowWindow( main_wnd, 0); ... if ( !CreateProcess( ..., (LPPROCESS_INFORMATION) &process_info.handle)) { /* I failed miserably */ return 0; }
/* debugger loop, process events */ for( ;;) { WaitForDebugEvent( ...) ... ContinueDebugEvent( ...) } ... --- snip debugger thread ---
After creation, the debugger thread immediately tries to hide the main window - owned by different thread - before launching the child process -> ShowWindow( SW_HIDE). Wine synchronously handles this using SendMessage().
The problem is that the main thread isn't able to process messages at this time because it's stuck in that incredibly stupid Sleep( some_magic_delay_that_ought_to_be_enough_to_bring_up_child_debugger_loop).
After the main thread delay expires - while debugger thread is still stuck in ShowWindow() call - the main thread immediately goes into a busy loop, checking the child process handle. Because the child process handle is initialized by code run after ShowWindow(), it will live-lock here.
I'm not sure how Windows handles this - I was too under impression that ShowWindow() should act synchronously if the window is owned by a different thread. If the app doesn't live lock in Windows, ShowWindow() behaviour is most likely different in Windows kernel.
Regards