OSDN Git Service

* cygtls.cc (_cygtls::handle_threadlist_exception): Make it clear that the
authorcgf <cgf>
Wed, 27 Feb 2008 17:16:45 +0000 (17:16 +0000)
committercgf <cgf>
Wed, 27 Feb 2008 17:16:45 +0000 (17:16 +0000)
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
winsup/cygwin/cygtls.cc
winsup/cygwin/exceptions.cc

index 428f737..554e93e 100644 (file)
@@ -1,3 +1,11 @@
+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-25  Corinna Vinschen  <corinna@vinschen.de>
 
        * dcrt0.cc (initial_env): Only use local buffer "buf" if DEBUGGING is
index af2723e..310f2e6 100644 (file)
@@ -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
index 3c00809..34defe5 100644 (file)
@@ -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.  */