https://bugs.winehq.org/show_bug.cgi?id=35344 Damjan Jovanovic <damjan.jov(a)gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download, source Component|-unknown |wineserver --- Comment #6 from Damjan Jovanovic <damjan.jov(a)gmail.com> --- Luckily it's an open-source Windows API app, ie. our dogfood, so we can see what's going on easily. We know fork() fails. In Cygwin's source code, the chain of events looks as follows: 1) fork() in winsup/cygwin/sigproc.h calls dofork(). 2) dofork() then tries to construct a local hold_everything of type hold_everything. 3) This class hold_everything in winsup/cygwin/sigproc.h has a field lock_signals signals which will be initialized by its constructor. 4) This constructor for lock_signals (same file) does: worked = sig_send (NULL, __SIGHOLD) == 0 5) That sig_send() in winsup/cygwin/sigproc.cc writes to HANDLE sendsig, which is the global static HANDLE my_sendsig in this particular call, then tries to WaitForSingleObject (pack.wakeup, WSSC) where WSSC is 60000 (which explains why fork() takes extremely long to fail). This however fails with WAIT_TIMEOUT so sig_send() sets errno=ENOSYS and returns with -1. Why does writing to my_sendsig not generate a response on pack.wakeup in due time? 1. During Cygwin startup, dll_crt0_0() in winsup/cygwin/dcrt0.cc calls sigproc_init(), as does dll_crt0_1() if dynamically_loaded is true. 2. sigproc_init() in winsup/cygwin/sigproc.cc calls: new cygthread (wait_sig, cygself, "sig"); 3. wait_sig() in winsup/cygwin/sigproc.cc is meant to signal pack.wakeup. But 3 never happens, that is, the new cygthread(...) does not result in the thread getting created and the wait_sig() function getting called to signal the fork() thread. Why not? cygthread (LPVOID_THREAD_START_ROUTINE start, LPVOID param, const char *name) : __name (name), func ((LPTHREAD_START_ROUTINE) start), arglen (0), arg (param), notify_detached (NULL) { QueueUserAPC (async_create, GetCurrentThread (), (ULONG_PTR) this); //create(); } If QueueUserAPC() is commented and create() uncommented, the thread starts and another failure happens later on, but for now let's debug QueueUserAPC(). async_create() definitely doesn't get called, so the failure is between QueueUserAPC() and the callback it is given. This looks like a Wine bug. In Wine: 1. kernel32.dll QueueUserAPC() 2. ntdll.dll NtQueueApcThread() 3. wineserver DECL_HANDLER(queue_apc) 4. wineserver queue_apc() Since the first 2 are trivial, let's focus on wineserver. queue_apc() calls get_apc_queue() to retrieve &thread->user_apc, then adds the APC to the queue, and since it's the first in the queue, calls wake_thread( thread ). wake_thread() returns 0, meaning the wait condition is still not satisfied. It's not clear whether this a problem though. Next, the APC must come out of wineserver and return to the application so it can be run and the thread created. How would that happen? --- Setting the component to "wineserver" for now, until I investigate the APC's return trip. Is there anyone more familiar with APCs that can help? -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.