summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <vinschen@redhat.com>2008-02-27 18:08:45 +0000
committerCorinna Vinschen <vinschen@redhat.com>2008-02-27 18:08:45 +0000
commit2c05c16b72860f3e75c9154958243c58a9909d7c (patch)
tree04cd6aa816545dff7817a528ff0ff928d0ac5450
parent514e5ff8ef15ddc1f9d98dbad74fd2b927f35a16 (diff)
downloadgdb-2c05c16b72860f3e75c9154958243c58a9909d7c.tar.gz
* 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/ChangeLog12
-rw-r--r--winsup/cygwin/cygtls.cc13
-rw-r--r--winsup/cygwin/exceptions.cc16
3 files changed, 31 insertions, 10 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 23268473026..ca3a0cf4a9f 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 0b37ed6b379..c2d7c2ed72e 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 = &el;). 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 = &el;
}
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index ad0af387166..2c9e0cb645f 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. */