* thread.cc (pthread::cancel): Re-allow asynchronous cancellation from
Cygwin code since it looks like the problem is Windows only.
This commit is contained in:
parent
bff08077a6
commit
2b165a453e
|
@ -1,3 +1,8 @@
|
||||||
|
2012-05-23 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* thread.cc (pthread::cancel): Re-allow asynchronous cancellation from
|
||||||
|
Cygwin code since it looks like the problem is Windows only.
|
||||||
|
|
||||||
2012-05-23 Corinna Vinschen <corinna@vinschen.de>
|
2012-05-23 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* thread.cc: Add a temporary workaround to help Cygwin along while
|
* thread.cc: Add a temporary workaround to help Cygwin along while
|
||||||
|
|
|
@ -631,42 +631,28 @@ pthread::cancel ()
|
||||||
SuspendThread (win32_obj_id);
|
SuspendThread (win32_obj_id);
|
||||||
if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT)
|
if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT)
|
||||||
{
|
{
|
||||||
static uintptr_t cyg_addr;
|
|
||||||
CONTEXT context;
|
CONTEXT context;
|
||||||
context.ContextFlags = CONTEXT_CONTROL;
|
context.ContextFlags = CONTEXT_CONTROL;
|
||||||
GetThreadContext (win32_obj_id, &context);
|
GetThreadContext (win32_obj_id, &context);
|
||||||
/* FIXME:
|
/* The OS is not foolproof in terms of asynchronous thread cancellation
|
||||||
|
and tends to hang infinitely if we change the instruction pointer.
|
||||||
File access (and probably more) in Cygwin is not foolproof in terms of
|
So just don't cancel asynchronously if the thread is currently
|
||||||
asynchronous thread cancellation. For instance, the cleanup of the
|
executing Windows code. Rely on deferred cancellation in this case. */
|
||||||
tmp_buf pointers needs to be changed to use pthread_cleanup_push/pop,
|
if (!cygtls->inside_kernel (&context))
|
||||||
rather than being hidden in the myfault class. We have to inspect
|
|
||||||
all Cygwin functions so that none of them is left in a wrong or
|
|
||||||
undefined state on thread cancellation.
|
|
||||||
|
|
||||||
For the time being, just disable asynchronous cancellation if the
|
|
||||||
thread is currently executing Cygwin or Windows code. Rely on
|
|
||||||
deferred cancellation in this case. */
|
|
||||||
if (!cyg_addr)
|
|
||||||
cyg_addr = (uintptr_t) GetModuleHandle ("cygwin1.dll");
|
|
||||||
if ((context.Eip < cyg_addr || context.Eip >= (uintptr_t) cygheap)
|
|
||||||
&& !cygtls->inside_kernel (&context))
|
|
||||||
{
|
{
|
||||||
context.Eip = (DWORD) pthread::static_cancel_self;
|
context.Eip = (DWORD) pthread::static_cancel_self;
|
||||||
SetThreadContext (win32_obj_id, &context);
|
SetThreadContext (win32_obj_id, &context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex.unlock ();
|
mutex.unlock ();
|
||||||
/* Setting the context to another function does not work if the thread is
|
/* See above. For instance, a thread which waits for a semaphore in sem_wait
|
||||||
waiting in WFMO. For instance, a thread which waits for a semaphore in
|
will call cancelable_wait which in turn calls WFMO. While this WFMO call
|
||||||
sem_wait will call cancelable_wait which in turn calls WFMO. While this
|
is cancelable by setting the thread's cancel_event object, the OS
|
||||||
WFMO call is cancelable by setting the thread's cancel_event object, the
|
apparently refuses to set the thread's context and continues to wait for
|
||||||
OS apparently refuses to set the thread's context and continues to wait
|
the WFMO conditions. This is *not* reflected in the return value of
|
||||||
for the WFMO conditions. This is *not* reflected in the return value of
|
|
||||||
SetThreadContext or ResumeThread, btw.
|
SetThreadContext or ResumeThread, btw.
|
||||||
So, what we do here is to set the cancel_event as well. This allows the
|
So, what we do here is to set the cancel_event as well to allow at least
|
||||||
WFMO call in cancelable_wait and elsewhere to return and to handle the
|
a deferred cancel. */
|
||||||
cancel request by itself. */
|
|
||||||
canceled = true;
|
canceled = true;
|
||||||
SetEvent (cancel_event);
|
SetEvent (cancel_event);
|
||||||
ResumeThread (win32_obj_id);
|
ResumeThread (win32_obj_id);
|
||||||
|
|
Loading…
Reference in New Issue