loader: On Mac, reserve the process's original thread for the frameworks. (try 2)
ken at codeweavers.com
Fri Nov 12 20:10:50 CST 2010
On Nov 12, 2010, at 5:14 AM, Alexandre Julliard wrote:
> Ken Thomases <ken at codeweavers.com> writes:
>> + /* This is a hack. We want to wait until the main thread has
>> + * really exited in response to our signal. However, Mac OS X
>> + * doesn't let us join the main thread for whatever reason.
>> + * It results in a SIGBUS. So, we just sleep for a bit and hope
>> + * it got enough time. */
>> + usleep(100);
> We need something more reliable than this.
I can't think of what it might be. I can wait for an acknowledgment from the main thread that the source callback has fired but that doesn't get us any closer to knowing when it has actually exited. (Before I encountered the pthread_join bug, the callback was actually passing the main thread's pthread_t back to terminate_main_thread with appropriate synchronization. So, I'm not averse to having such two-way communication, but once I gave up on pthread_join, I backed all of that out as only giving false confidence.)
The same applies to pthread cancellation cleanup handlers and thread-specific data destructors. They happen very late in the thread's lifetime, but don't let us know it's actually gone (such that execve will succeed).
I'm open to suggestions. pthread_join is really the only correct tool for this job.
Of course, any fix for pthread_join won't help. It will (obviously) come in some future version of Mac OS X, while the ENOTSUP from execve has already been solved in Snow Leopard. So, in reality, terminating the main thread is only necessary on Leopard and there won't be any fixes forthcoming for that version.
I have been treating this as a best-effort sort of situation. Should the attempt to terminate the main thread fail, we'll just go ahead and attempt the exec, anyway. Either it will succeed or it won't. (For what it's worth, create_process has some work yet to do after terminate_main_thread returns before it attempts the exec. So, there's a bit more than just that usleep, not that that makes it any more of a sure thing.)
I suppose we could put a loop around the exec call, such that we sleep and retry if it returns ENOTSUP. However, if terminate_main_thread was unsuccessful, or if ENOTSUP can occur for other reasons, that might be an infinite loop.
More information about the wine-devel