Feature #5788 » patch.diff
thread.c | ||
---|---|---|
native_thread_init_stack(th);
|
||
}
|
||
static void thread_run_at_exit(rb_thread_t *th);
|
||
static int
|
||
thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_start)
|
||
{
|
||
... | ... | |
th->value = Qnil;
|
||
}
|
||
thread_run_at_exit(th);
|
||
th->status = THREAD_KILLED;
|
||
thread_debug("thread end: %p\n", (void *)th);
|
||
... | ... | |
return str;
|
||
}
|
||
static void
|
||
thread_run_at_exit(rb_thread_t *th)
|
||
{
|
||
int i;
|
||
VALUE at_exit;
|
||
if(th->at_exit){
|
||
at_exit = th->at_exit;
|
||
for (i=0; i<RARRAY_LEN(at_exit); i++) {
|
||
rb_proc_call(RARRAY_PTR(at_exit)[i], rb_ary_new());
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
VALUE
|
||
rb_thread_define_at_exit(VALUE thread)
|
||
{
|
||
rb_thread_t *th;
|
||
VALUE proc;
|
||
if (!rb_block_given_p()) {
|
||
rb_raise(rb_eArgError, "called without a block");
|
||
}
|
||
proc = rb_block_proc();
|
||
GetThreadPtr(thread, th);
|
||
if (th == th->vm->main_thread) {
|
||
rb_set_end_proc(rb_call_end_proc, proc);
|
||
} else {
|
||
if (th->at_exit) {
|
||
rb_ary_push(th->at_exit, proc);
|
||
} else {
|
||
th->at_exit = rb_ary_new3(1, proc);
|
||
}
|
||
}
|
||
return thread;
|
||
}
|
||
VALUE
|
||
rb_thread_local_aref(VALUE thread, ID id)
|
||
{
|
||
... | ... | |
rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0);
|
||
rb_define_method(rb_cThread, "group", rb_thread_group, 0);
|
||
rb_define_method(rb_cThread, "backtrace", rb_thread_backtrace_m, 0);
|
||
rb_define_method(rb_cThread, "at_exit", rb_thread_define_at_exit, 0);
|
||
rb_define_method(rb_cThread, "inspect", rb_thread_inspect, 0);
|
||
vm_core.h | ||
---|---|---|
/* storage */
|
||
st_table *local_storage;
|
||
VALUE at_exit;
|
||
struct rb_thread_struct *join_list_next;
|
||
struct rb_thread_struct *join_list_head;
|
||