From 4be5d446810858f13275d593784673b810b6e2c6 Mon Sep 17 00:00:00 2001 From: cgf Date: Wed, 27 Feb 2008 17:16:45 +0000 Subject: [PATCH] * cygtls.cc (_cygtls::handle_threadlist_exception): Make it clear that the function never actually returns. * exceptions.cc (_cygtls::handle_exceptions): Jump out of function rather than returning to avoid meddling by previously installed exception handlers. --- winsup/cygwin/ChangeLog | 8 ++++++++ winsup/cygwin/cygtls.cc | 4 ++-- winsup/cygwin/exceptions.cc | 16 +++++++++++++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 428f737073..554e93efad 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,11 @@ +2008-02-27 Christopher Faylor + + * cygtls.cc (_cygtls::handle_threadlist_exception): Make it clear that + the function never actually returns. + * exceptions.cc (_cygtls::handle_exceptions): Jump out of function + rather than returning to avoid meddling by previously installed + exception handlers. + 2008-02-25 Corinna Vinschen * dcrt0.cc (initial_env): Only use local buffer "buf" if DEBUGGING is diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index af2723e955..310f2e6377 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -221,7 +221,7 @@ _cygtls::set_siginfo (sigpacket *pack) infodata = pack->si; } -extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD); +extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD) __attribute__ ((noreturn)); int _cygtls::handle_threadlist_exception (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *c, void *) { @@ -248,7 +248,7 @@ _cygtls::handle_threadlist_exception (EXCEPTION_RECORD *e, exception_list *frame cygheap->threadlist[threadlist_ix]->remove (INFINITE); threadlist_ix = 0; RtlUnwind (frame, threadlist_exception_return, e, 0); - return 0; + /* Never returns */ } /* Set up the exception handler for the current thread. The x86 uses segment diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 3c00809530..34defe51b8 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -659,7 +659,21 @@ _cygtls::handle_exceptions (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT sig_send (NULL, si, &me); // Signal myself me.incyg--; e->ExceptionFlags = 0; - return 0; + /* The OS adds an exception list frame to the stack. It expects to be + able to remove this entry after the exception handler returned. + However, when unwinding to our frame, our frame becomes the uppermost + frame on the stack (%fs:0 points to frame). This way, our frame + is removed from the exception stack and just disappears. So, we can't + just return here or things will be screwed up by the helpful function + in (presumably) ntdll.dll. + + So, instead, we will do the equivalent of a longjmp here and return + to the caller without visiting any of the helpful code installed prior + to this function. This should work ok, since a longjmp() out of here has + to work if linux signal semantics are to be maintained. */ + + SetThreadContext (GetCurrentThread (), in); + return 0; /* Never actually returns. This is just to keep gcc happy. */ } /* Utilities to call a user supplied exception handler. */ -- 2.11.0