pike.git / src / threads.c

version» Context lines:

pike.git/src/threads.c:1206:   }      PMOD_EXPORT struct object *thread_for_id(THREAD_T tid)   {    struct thread_state *s = thread_state_for_id(tid);    return (s == NULL? NULL : THREADSTATE2OBJ(s));    /* See NB in thread_state_for_id. Lifespan of result can be prolonged    by incrementing refcount though. */   }    + static inline void CALL_WITH_ERROR_HANDLING(struct thread_state *state, +  void (*func)(void *ctx), +  void *ctx) + { +  JMP_BUF back; +  +  if(SETJMP(back)) +  { +  if(throw_severity <= THROW_ERROR) { +  if (state->thread_obj) { +  /* Copy the thrown exit value to the thread_state here, +  * if the thread hasn't been destructed. */ +  assign_svalue(&state->result, &throw_value); +  } +  +  call_handle_error(); +  } +  +  if(throw_severity == THROW_EXIT) +  { +  /* This is too early to get a clean exit if DO_PIKE_CLEANUP is +  * active. Otoh it cannot be done later since it requires the +  * evaluator stacks in the gc calls. It's difficult to solve +  * without handing over the cleanup duty to the main thread. */ +  pike_do_exit(throw_value.u.integer); +  } +  +  state->status = THREAD_ABORTED; +  } else { +  back.severity=THROW_EXIT; +  func(ctx); +  } +  +  UNSETJMP(back); + } +    PMOD_EXPORT void call_with_interpreter(void (*func)(void *ctx), void *ctx)   {    struct thread_state *state;       if((state = thread_state_for_id(th_self()))!=NULL) {    /* This is a pike thread. Do we have the interpreter lock? */    if(!state->swapped) {    /* Yes. Go for it... */   #ifdef PIKE_DEBUG    /* Ensure that the thread isn't loose. */    int is_loose = state->debug_flags & THREAD_DEBUG_LOOSE;    state->debug_flags &= ~THREAD_DEBUG_LOOSE;   #endif    -  func(ctx); +  CALL_WITH_ERROR_HANDLING(state, func, ctx);      #ifdef PIKE_DEBUG    /* Restore the looseness property of the thread. */    state->debug_flags |= is_loose;   #endif    } else {    /* Nope, let's get it... */    mt_lock_interpreter();    SWAP_IN_THREAD(state);    DO_IF_DEBUG(state->debug_flags &= ~THREAD_DEBUG_LOOSE;)    -  func(ctx); +  CALL_WITH_ERROR_HANDLING(state, func, ctx);       /* Restore */    DO_IF_DEBUG(state->debug_flags |= THREAD_DEBUG_LOOSE;)    SWAP_OUT_THREAD(state);    mt_unlock_interpreter();    }    } else {    /* Not a pike thread. Create a temporary thread_id... */    struct object *thread_obj;    struct Pike_interpreter_struct new_interpreter;
pike.git/src/threads.c:1255:    Pike_interpreter_pointer = &new_interpreter;    init_interpreter();    Pike_interpreter.stack_top=((char *)&state)+ (thread_stack_size-16384) * STACK_DIRECTION;    Pike_interpreter.recoveries = NULL;    thread_obj = fast_clone_object(thread_id_prog);    INIT_THREAD_STATE((struct thread_state *)(thread_obj->storage +    thread_storage_offset));    num_threads++;    thread_table_insert(Pike_interpreter.thread_state);    -  func(ctx); +  CALL_WITH_ERROR_HANDLING(Pike_interpreter.thread_state, func, ctx);       cleanup_interpret(); /* Must be done before EXIT_THREAD_STATE */    Pike_interpreter.thread_state->status=THREAD_EXITED;    co_signal(&Pike_interpreter.thread_state->status_change);    thread_table_delete(Pike_interpreter.thread_state);    EXIT_THREAD_STATE(Pike_interpreter.thread_state);    Pike_interpreter.thread_state=NULL;    free_object(thread_obj);    thread_obj = NULL;    num_threads--;