diff --git a/ChangeLog b/ChangeLog index 8619d6ab08..424eff3ce7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +Sun May 11 13:14:09 2008 Tanaka Akira + + * thread.c (thread_cleanup_func_before_exec): extracted from + thread_cleanup_func not to touch pthread data. + pthread_cond_destroy in forked process may cause deadlock on + Debian GNU/Linux Etch on x86, x86-64 and IA64. + this doesn't cause resource leak because the process will exec soon. + (terminate_atfork_before_exec_i): defined. + (rb_thread_atfork_before_exec): defined. + + * include/ruby/intern.h (rb_thread_atfork_before_exec): declared. + + * process.c (rb_exec_atfork): call rb_thread_atfork_before_exec + instead of rb_thread_atfork. + + * io.c (popen_exec): call rb_thread_atfork_before_exec instead of + rb_thread_atfork. + Sat May 10 22:14:03 2008 Yukihiro Matsumoto * string.c (tr_trans): single '^' does not mean negation. diff --git a/include/ruby/intern.h b/include/ruby/intern.h index 8f9b2940ea..8b31576c5e 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -308,6 +308,7 @@ VALUE rb_thread_main(void); VALUE rb_thread_local_aref(VALUE, ID); VALUE rb_thread_local_aset(VALUE, ID, VALUE); void rb_thread_atfork(void); +void rb_thread_atfork_before_exec(void); VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int),VALUE,VALUE); /* file.c */ VALUE rb_file_s_expand_path(int, VALUE *); diff --git a/io.c b/io.c index ad0b6ffda3..6bd0037d22 100644 --- a/io.c +++ b/io.c @@ -3671,7 +3671,7 @@ popen_exec(void *pp) { struct popen_arg *p = (struct popen_arg*)pp; - rb_thread_atfork(); + rb_thread_atfork_before_exec(); return rb_exec(p->execp); } #endif diff --git a/process.c b/process.c index 58bd08b81f..4607edeedf 100644 --- a/process.c +++ b/process.c @@ -2103,7 +2103,7 @@ rb_exec(const struct rb_exec_arg *e) static int rb_exec_atfork(void* arg) { - rb_thread_atfork(); + rb_thread_atfork_before_exec(); return rb_exec(arg); } #endif diff --git a/thread.c b/thread.c index 21d43edc27..5b48721e71 100644 --- a/thread.c +++ b/thread.c @@ -273,7 +273,7 @@ rb_thread_terminate_all(void) } static void -thread_cleanup_func(void *th_ptr) +thread_cleanup_func_before_exec(void *th_ptr) { rb_thread_t *th = th_ptr; th->status = THREAD_KILLED; @@ -281,6 +281,13 @@ thread_cleanup_func(void *th_ptr) #ifdef __ia64 th->machine_register_stack_start = th->machine_register_stack_end = 0; #endif +} + +static void +thread_cleanup_func(void *th_ptr) +{ + rb_thread_t *th = th_ptr; + thread_cleanup_func_before_exec(th_ptr); native_thread_destroy(th); } @@ -2064,6 +2071,32 @@ rb_thread_atfork(void) st_insert(vm->living_threads, thval, (st_data_t) th->thread_id); } +static int +terminate_atfork_before_exec_i(st_data_t key, st_data_t val, rb_thread_t *current_th) +{ + VALUE thval = key; + rb_thread_t *th; + GetThreadPtr(thval, th); + + if (th != current_th) { + thread_cleanup_func_before_exec(th); + } + return ST_CONTINUE; +} + +void +rb_thread_atfork_before_exec(void) +{ + rb_thread_t *th = GET_THREAD(); + rb_vm_t *vm = th->vm; + VALUE thval = th->self; + vm->main_thread = th; + + st_foreach(vm->living_threads, terminate_atfork_before_exec_i, (st_data_t)th); + st_clear(vm->living_threads); + st_insert(vm->living_threads, thval, (st_data_t) th->thread_id); +} + struct thgroup { int enclosed; VALUE group;