pike.git / src / threads.c

version» Context lines:

pike.git/src/threads.c:1777:    SWAP_IN_CURRENT_THREAD();    }       DEBUG_CHECK_THREAD();       THREADS_FPRINTF(0, (stderr,"new_thread_func(): Thread %p inited\n",    arg.thread_state));       if(SETJMP(back))    { -  if(throw_severity <= THROW_ERROR) +  if(throw_severity <= THROW_ERROR) { +  if (thread_state->thread_obj) { +  /* Copy the thrown exit value to the thread_state here, +  * if the thread hasn't been destructed. */ +  assign_svalue(&thread_state->result, &throw_value); +  } +     call_handle_error(); -  else if(throw_severity == THROW_EXIT) +  } +  +  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); -  } else if (thread_state->thread_obj) { -  /* Copy the thrown exit value to the thread_state here, -  * if the thread hasn't been destructed. */ -  assign_svalue(&thread_state->result, &throw_value); +     } -  +  +  thread_state->status = THREAD_ABORTED;    } else {    INT32 args=arg.args->size;    back.severity=THROW_EXIT;    push_array_items(arg.args);    arg.args=0;    f_call_function(args);       /* Copy return value to the thread_state here, if the thread    * object hasn't been destructed. */    if (thread_state->thread_obj)    assign_svalue(&thread_state->result, Pike_sp-1);    pop_stack(); -  +  +  thread_state->status = THREAD_EXITED;    }       UNSETJMP(back);       DEBUG_CHECK_THREAD();       if(thread_state->thread_local != NULL) {    free_mapping(thread_state->thread_local);    thread_state->thread_local = NULL;    }    -  thread_state->status = THREAD_EXITED; +     co_broadcast(&thread_state->status_change);       THREADS_FPRINTF(0, (stderr,"new_thread_func(): Thread %p done\n",    arg.thread_state));       /* This thread is now officially dead. */       while(Pike_fp)    POP_PIKE_FRAME();   
pike.git/src/threads.c:2676:      /*! @decl int status()    *!    *! Returns the status of the thread.    *!    *! @returns    *! @int    *! @value Thread.THREAD_NOT_STARTED    *! @value Thread.THREAD_RUNNING    *! @value Thread.THREAD_EXITED +  *! @value Thread.THREAD_ABORTED    *! @endint    */   void f_thread_id_status(INT32 args)   {    pop_n_elems(args);    push_int(THIS_THREAD->status);   }      /*! @decl protected string _sprintf(int c)    *!
pike.git/src/threads.c:2721:   void f_thread_id_id_number(INT32 args)   {    pop_n_elems(args);    push_int64(PTR_TO_INT(THREAD_T_TO_PTR(THIS_THREAD->id)));   }      /*! @decl mixed wait()    *!    *! Waits for the thread to complete, and then returns    *! the value returned from the thread function. +  *! +  *! @throws +  *! Rethrows the error thrown by the thread if it exited by +  *! throwing an error.    */   static void f_thread_id_result(INT32 UNUSED(args))   {    struct thread_state *th=THIS_THREAD; -  +  int th_status;       if (threads_disabled) {    Pike_error("Cannot wait for threads when threads are disabled!\n");    }       th->waiting++;       THREADS_FPRINTF(0, (stderr, "Thread->wait(): Waiting for thread_state %p "    "(state:%d).\n", th, th->status)); -  while(th->status != THREAD_EXITED) { +  while(th->status < THREAD_EXITED) {    SWAP_OUT_CURRENT_THREAD();    co_wait_interpreter(&th->status_change);    SWAP_IN_CURRENT_THREAD();    check_threads_etc();    THREADS_FPRINTF(0,    (stderr, "Thread->wait(): Waiting for thread_state %p "    "(state:%d).\n", th, th->status));    }    -  +  th_status = th->status; +     assign_svalue_no_free(Pike_sp, &th->result);    Pike_sp++;    dmalloc_touch_svalue(Pike_sp-1);       th->waiting--;       if (!th->thread_obj)    /* Do this only if exit_thread_obj already has run. */    cleanup_thread_state (th); -  +  +  if (th_status == THREAD_ABORTED) f_throw(1);   }      static int num_pending_interrupts = 0;   static struct callback *thread_interrupt_callback = NULL;      static void check_thread_interrupt(struct callback *foo,    void *UNUSED(bar), void *UNUSED(gazonk))   {    if (Pike_interpreter.thread_state->flags & THREAD_FLAG_INHIBIT) {    return;
pike.git/src/threads.c:3363:    OPT_EXTERNAL_DEPEND);       ADD_EFUN("all_threads",f_all_threads,    tFunc(tNone,tArr(tObjIs_THREAD_ID)),    OPT_EXTERNAL_DEPEND);       /* Some constants... */    add_integer_constant("THREAD_NOT_STARTED", THREAD_NOT_STARTED, 0);    add_integer_constant("THREAD_RUNNING", THREAD_RUNNING, 0);    add_integer_constant("THREAD_EXITED", THREAD_EXITED, 0); +  add_integer_constant("THREAD_ABORTED", THREAD_ABORTED, 0);       original_interpreter = Pike_interpreter_pointer;    backend_thread_obj = fast_clone_object(thread_id_prog);    INIT_THREAD_STATE((struct thread_state *)(backend_thread_obj->storage +    thread_storage_offset));    thread_table_insert(Pike_interpreter.thread_state);   }      #ifdef DO_PIKE_CLEANUP   void cleanup_all_other_threads (void)