pike.git/src/error.c:120: Inside #if defined(PIKE_DEBUG)
/* push_int((ptrdiff_t)location); */
/* mapping_insert(recovery_lookup, Pike_sp-2, Pike_sp-1); */
/* pop_n_elems(2); */
/* } */
#endif
return r;
}
PMOD_EXPORT DECLSPEC(noreturn) void pike_throw(void) ATTRIBUTE((noreturn))
{
+ struct svalue save_throw_value;
+
+ /* Save the value to be thrown in case error handlers etc below
+ * call eg safe_apply() et al, or cause a thread switch to
+ * code that does.
+ */
+ move_svalue(&save_throw_value, &throw_value);
+ mark_free_svalue(&throw_value);
+
#ifdef TRACE_UNFINISHED_TYPE_FIELDS
accept_unfinished_type_fields++;
#endif
while(Pike_interpreter.recoveries && throw_severity > Pike_interpreter.recoveries->severity)
{
while(Pike_interpreter.recoveries->onerror)
{
ONERROR *err = Pike_interpreter.recoveries->onerror;
while(Pike_fp != err->frame_pointer)
pike.git/src/error.c:192:
Pike_fatal("Popped out of stack frames.\n");
#endif
POP_PIKE_FRAME();
}
#ifdef PIKE_DEBUG
if(Pike_sp - Pike_interpreter.evaluator_stack < Pike_interpreter.recoveries->stack_pointer)
Pike_fatal("Stack error in error.\n");
#endif
- pop_n_elems(Pike_sp - Pike_interpreter.evaluator_stack - Pike_interpreter.recoveries->stack_pointer);
+ /* Note: The pop_stack() below may trigger destruct callbacks being called
+ * for objects having PROGRAM_DESTRUCT_IMMEDIATE. These may
+ * in turn throw (caught) errors and zap throw_value.
+ *
+ * Note: We can not use pop_n_elems() here as a nested error in an
+ * immediate destruct callback may zap the stack for us during
+ * our popping.
+ */
+ while (Pike_sp > Pike_interpreter.evaluator_stack + Pike_interpreter.recoveries->stack_pointer) {
+ pop_stack();
+ }
Pike_mark_sp = Pike_interpreter.mark_stack + Pike_interpreter.recoveries->mark_sp;
-
+ /* Move the value to be thrown back so that it can be caught. */
+ free_svalue(&throw_value);
+ move_svalue(&throw_value, &save_throw_value);
+
#if defined(DEBUG_MALLOC) && defined(PIKE_DEBUG)
/* This will tell us where the value was caught (I hope) */
if(REFCOUNTED_TYPE(TYPEOF(throw_value)))
{
debug_malloc_update_location(throw_value.u.refs,
Pike_interpreter.recoveries->file);
debug_malloc_touch(throw_value.u.refs);
}
#endif