diff mbox

[gccgo] Fixes for stack unwinding

Message ID mcrbpb0cj1y.fsf@dhcp-172-17-9-151.mtv.corp.google.com
State New
Headers show

Commit Message

Ian Lance Taylor June 24, 2010, 7:44 p.m. UTC
This patch includes some fixes for stack unwinding in Go.

1) Don't let the unwind code split the stack.

2) Exiting a thread causes a stack unwind.  Don't allocate memory
during this unwind.

3) Treat cleanups correctly--not as an exception handler.

Committed to gccgo branch.

Ian
diff mbox

Patch

diff -r c066a9b9c7bb libgo/runtime/go-unwind.c
--- a/libgo/runtime/go-unwind.c	Thu Jun 24 12:36:37 2010 -0700
+++ b/libgo/runtime/go-unwind.c	Thu Jun 24 12:37:40 2010 -0700
@@ -47,7 +47,12 @@ 
 {
   struct _Unwind_Exception *hdr;
 
-  if (__go_panic_defer->__is_foreign)
+  if (__go_panic_defer == NULL)
+    {
+      /* Some other language has thrown an exception.  We know there
+	 are no defer handlers, so there is nothing to do.  */
+    }
+  else if (__go_panic_defer->__is_foreign)
     {
       struct __go_panic_stack *n;
       _Bool was_recovered;
@@ -210,6 +215,11 @@ 
   return p;
 }
 
+/* The personality function is invoked when unwinding the stack due to
+   a panic.  Its job is to find the cleanup and exception handlers to
+   run.  We can't split the stack here, because we won't be able to
+   unwind from that split.  */
+
 #ifdef __ARM_EABI_UNWINDER__
 /* ARM EABI personality routines must also unwind the stack.  */
 #define CONTINUE_UNWINDING \
@@ -234,7 +244,8 @@ 
 #ifdef __ARM_EABI_UNWINDER__
 _Unwind_Reason_Code
 PERSONALITY_FUNCTION (_Unwind_State, struct _Unwind_Exception *,
-		      struct _Unwind_Context *);
+		      struct _Unwind_Context *)
+  __attribute__ ((no_split_stack, flatten));
 
 _Unwind_Reason_Code
 PERSONALITY_FUNCTION (_Unwind_State state,
@@ -243,7 +254,8 @@ 
 #else
 _Unwind_Reason_Code
 PERSONALITY_FUNCTION (int, _Unwind_Action, _Unwind_Exception_Class,
-		      struct _Unwind_Exception *, struct _Unwind_Context *);
+		      struct _Unwind_Exception *, struct _Unwind_Context *)
+  __attribute__ ((no_split_stack, flatten));
 
 _Unwind_Reason_Code
 PERSONALITY_FUNCTION (int version,
@@ -316,6 +328,7 @@ 
   if (! ip_before_insn)
     --ip;
   landing_pad = 0;
+  action_record = NULL;
 
 #ifdef __USING_SJLJ_EXCEPTIONS__
   /* The given "IP" is an index into the call-site table, with two
@@ -380,18 +393,29 @@ 
     }
 
   if (actions & _UA_SEARCH_PHASE)
-    return _URC_HANDLER_FOUND;
+    {
+      if (action_record == 0)
+	{
+	  /* This indicates a cleanup rather than an exception
+	     handler.  */
+	  CONTINUE_UNWINDING;
+	}
 
+      return _URC_HANDLER_FOUND;
+    }
+
+  /* It's possible for __go_panic_defer to be NULL here for an
+     exception thrown by a language other than Go.  */
   if (__go_panic_defer == NULL)
     {
       if (!is_foreign)
-	abort();
-      __go_panic_defer = ((struct __go_panic_defer_struct *)
-			  __go_alloc (sizeof (struct __go_panic_defer_struct)));
+	abort ();
     }
-
-  __go_panic_defer->__exception = ue_header;
-  __go_panic_defer->__is_foreign = is_foreign;
+  else
+    {
+      __go_panic_defer->__exception = ue_header;
+      __go_panic_defer->__is_foreign = is_foreign;
+    }
 
   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
 		 (_Unwind_Ptr) ue_header);