  } rb_control_frame_t;
  
  typedef struct rb_block_struct {
-@@ -390,6 +395,17 @@
+@@ -390,6 +395,16 @@
      /* passing state */
      int state;
  

 
 	if (iseq->insn_info_table[0].position == pos) goto found;
 	for (i = 1; i < iseq->insn_info_size; i++) {
@@ -1164,8 +1165,20 @@
 
 	while (th->cfp->pc == 0 || th->cfp->iseq == 0) {
 	    if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) {
-		const rb_method_entry_t *me = th->cfp->me;
-		EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass);
+		/* rocky: The below tests and assignments are not
+		   quite right.  The problem I am having is when a
+		   there is an exception in hook code raised from a C
+		   return event. This causes the below EXEC_EVENT_HOOK to
+		   loop indefinitely. The below has the bad effect of
+		   not reseting exec_event_tracing sometimes.
+		 */
+		if (0 == th->tracing && 0 == th->exec_event_tracing) {
+		    const rb_method_entry_t *me = th->cfp->me;
+		    th->exec_event_tracing = 1;
+		    EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, 
+				    me->called_id, me->klass);
+		    th->exec_event_tracing = 0;
+		}
 	    }
 	    th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
 	}
@@ -1333,7 +1346,7 @@
 
 	    switch (VM_FRAME_TYPE(th->cfp)) {
 	      case VM_FRAME_MAGIC_METHOD:
-		EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, th->cfp->self, 0, 0);
+		EXEC_EVENT_RETURN_HOOK(th, RUBY_EVENT_RETURN, th->cfp->self, 0, 0);
 		break;
 	      case VM_FRAME_MAGIC_CLASS:
 		EXEC_EVENT_HOOK(th, RUBY_EVENT_END, th->cfp->self, 0, 0);
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 28682)

 	rb_thread_method_id_and_class(GET_THREAD(), &id, &klass);
     }
     if (id == ID_ALLOCATOR)
@@ -4088,7 +4181,7 @@
 ruby_suppress_tracing(VALUE (*func)(VALUE, int), VALUE arg, int always)
 {
     rb_thread_t *th = GET_THREAD();
-    int state, tracing;
+    int state, tracing, cfp_tracing;
     volatile int raised;
     VALUE result = Qnil;
 
@@ -4097,6 +4190,10 @@
     }
     else {
 	th->tracing = 1;
+	cfp_tracing = th->cfp->tracing;
+       /* FIXME: The following doesn't work because this needs to be done in the
+          hook frame which we haven't created yet. */	
+	/* th->cfp->tracing |= VM_FRAME_TRACE_OFF; */
     }
 
     raised = rb_threadptr_reset_raised(th);
@@ -4112,6 +4209,8 @@
     POP_TAG();
 
     th->tracing = tracing;
+    /* FIXME: not really needed see above FIXME. */
+    th->cfp->tracing = cfp_tracing;
     if (state) {
 	JUMP_TAG(state);
     }
@@ -4234,9 +4333,11 @@
     rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
 
     /* trace */
