* thread.cc (pthread::cancel): Only allow asynchronous cancellation
if the thread is not executing Cygwin or Windows code. Explain why.
This commit is contained in:
parent
750329ae90
commit
86b35406f2
|
@ -1,3 +1,8 @@
|
||||||
|
2012-05-23 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* thread.cc (pthread::cancel): Only allow asynchronous cancellation
|
||||||
|
if the thread is not executing Cygwin or Windows code. Explain why.
|
||||||
|
|
||||||
2012-05-23 Corinna Vinschen <corinna@vinschen.de>
|
2012-05-23 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* thread.cc (pthread::precreate): Make sure mutex is recursive.
|
* thread.cc (pthread::precreate): Make sure mutex is recursive.
|
||||||
|
|
|
@ -569,11 +569,30 @@ 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);
|
||||||
context.Eip = (DWORD) pthread::static_cancel_self;
|
/* FIXME:
|
||||||
SetThreadContext (win32_obj_id, &context);
|
|
||||||
|
File access (and probably more) in Cygwin is not foolproof in terms of
|
||||||
|
asynchronous thread cancellation. For instance, the cleanup of the
|
||||||
|
tmp_buf pointers needs to be changed to use pthread_cleanup_push/pop,
|
||||||
|
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;
|
||||||
|
SetThreadContext (win32_obj_id, &context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mutex.unlock ();
|
mutex.unlock ();
|
||||||
/* Setting the context to another function does not work if the thread is
|
/* Setting the context to another function does not work if the thread is
|
||||||
|
|
Loading…
Reference in New Issue