]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix handling of multiple signal deliveries in a row
authorJosef Weidendorfer <Josef.Weidendorfer@gmx.de>
Wed, 1 Jul 2009 23:56:23 +0000 (23:56 +0000)
committerJosef Weidendorfer <Josef.Weidendorfer@gmx.de>
Wed, 1 Jul 2009 23:56:23 +0000 (23:56 +0000)
This fixes bug 136154.

Background:
The function stack - CLG_(current_fn_stack) - is a stack of
pointers to the fn_node structs of the currently active
functions. This stack is used for determining current context
from call chain to current function, and modified on entering
(via push_cxt) and leaving a function.
Entering a signal handler will push a 0 to the function stack
to make the context only dependend on the call chain inside of
the signal handler.
Thus, delivering two signals in a row should push two times a
0 value onto the function stack. However, the second 0-push was
incorrectly suppressed, leading to a failed assertion when
returning from the 2nd signal handler.

This also fixes a bug with incorrectly zeroing global cost
counters when changing the execution context, introduced with
r10386.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10399

callgrind/context.c
callgrind/threads.c

index 9abe6d15197747134f53d6dd8314ac992d9ab791..eb478fd5df7b6050a1c5e5b9228eb299219a9cbd 100644 (file)
@@ -276,7 +276,7 @@ Context* CLG_(get_cxt)(fn_node** fn)
 
 /**
  * Change execution context by calling a new function from current context
- *
+ * Pushing 0x0 specifies a marker for a signal handler entry
  */
 void CLG_(push_cxt)(fn_node* fn)
 {
@@ -294,7 +294,7 @@ void CLG_(push_cxt)(fn_node* fn)
   cs->entry[cs->sp].cxt = CLG_(current_state).cxt;
   cs->entry[cs->sp].fn_sp = CLG_(current_fn_stack).top - CLG_(current_fn_stack).bottom;
 
-  if (*(CLG_(current_fn_stack).top) == fn) return;
+  if (fn && (*(CLG_(current_fn_stack).top) == fn)) return;
   if (fn && (fn->group>0) &&
       ((*(CLG_(current_fn_stack).top))->group == fn->group)) return;
 
@@ -318,11 +318,10 @@ void CLG_(push_cxt)(fn_node* fn)
     CLG_(current_fn_stack).size = new_size;
   }
 
-  if (*(CLG_(current_fn_stack).top) == 0) {
+  if (fn && (*(CLG_(current_fn_stack).top) == 0)) {
     UInt *pactive;
 
     /* this is first function: increment its active count */
-    CLG_ASSERT(fn != 0);
     pactive = CLG_(get_fn_entry)(fn->number);
     (*pactive)++;
   }
index d08bb7234a24e99d77ecb5e5613b459240a495ba..196fb875fa9f1de287f425c4eb6983303b6ab146 100644 (file)
@@ -208,17 +208,16 @@ void CLG_(pre_signal)(ThreadId tid, Int sigNum, Bool alt_stack)
     /* save current execution state */
     exec_state_save();
 
-    /* setup current state for a spontaneous call */
-    CLG_(init_exec_state)( &CLG_(current_state) );
-    CLG_(push_cxt)(0);
-
     /* setup new cxtinfo struct for this signal handler */
     es = push_exec_state(sigNum);
-    CLG_(init_cost)( CLG_(sets).full, es->cost);
+    // because of this, below call to init_exec_state will zero es->cost
     CLG_(current_state).cost = es->cost;
     es->call_stack_bottom = CLG_(current_call_stack).sp;
 
+    /* setup current state for a spontaneous call */
+    CLG_(init_exec_state)( &CLG_(current_state) );
     CLG_(current_state).sig = sigNum;
+    CLG_(push_cxt)(0);
 }
 
 /* Run post-signal if the stackpointer for call stack is at
@@ -418,6 +417,7 @@ exec_state* exec_state_save(void)
   es->jmps_passed = CLG_(current_state).jmps_passed;
   es->bbcc        = CLG_(current_state).bbcc;
   es->nonskipped  = CLG_(current_state).nonskipped;
+  CLG_ASSERT(es->cost == CLG_(current_state).cost);
 
   CLG_DEBUGIF(1) {
     CLG_DEBUG(1, "  cxtinfo_save(sig %d): collect %s, jmps_passed %d\n",