diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2008-02-27 18:08:45 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2008-02-27 18:08:45 +0000 |
commit | 47b65da0c18650d0d035d1386a657b8f22d73e9d (patch) | |
tree | ae02a609f4698cb29f922c6d9acdd6f9b115dd79 | |
parent | c225d7f3c1e2c9323b52a055d28bdb63230c305d (diff) | |
download | newlib-47b65da0c18650d0d035d1386a657b8f22d73e9d.zip newlib-47b65da0c18650d0d035d1386a657b8f22d73e9d.tar.gz newlib-47b65da0c18650d0d035d1386a657b8f22d73e9d.tar.bz2 |
* cygtls.cc (_cygtls::init_exception_handler): Fix comment.
* 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.
-rw-r--r-- | winsup/cygwin/ChangeLog | 12 | ||||
-rw-r--r-- | winsup/cygwin/cygtls.cc | 13 | ||||
-rw-r--r-- | winsup/cygwin/exceptions.cc | 16 |
3 files changed, 31 insertions, 10 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 2326847..ca3a0cf 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,15 @@ +2008-02-27 Corinna Vinschen <corinna@vinschen.de> + + * cygtls.cc (_cygtls::init_exception_handler): Fix comment. + +2008-02-27 Christopher Faylor <me+cygwin@cgf.cx> + + * 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-21 Christopher Faylor <me+cygwin@cgf.cx> * dtable.cc (dtable::init_std_file_from_handle): Try harder to make a diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index 0b37ed6..c2d7c2e 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -222,7 +222,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 *) { @@ -249,7 +249,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 @@ -270,13 +270,8 @@ _cygtls::init_exception_handler (exception_handler *eh) At one point this was a loop (el.prev = ⪙). This outsmarted the above behaviour. Unfortunately this trick doesn't work anymore with Windows 2008, which irremediably gets into an endless loop, taking 100% - CPU. That's why we reverted to a normal SEH chain. - - On the bright side, Windows' behaviour is covered by POSIX: - - "If and when the function returns, if the value of sig was SIGFPE, - SIGILL, or SIGSEGV or any other implementation-defined value - corresponding to a computational exception, the behavior is undefined." */ + CPU. That's why we reverted to a normal SEH chain and changed the way + the exception handler returns to the application. */ el.prev = _except_list; _except_list = ⪙ } diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index ad0af38..2c9e0cb 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -664,7 +664,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. */ |