summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog18
-rw-r--r--include/ruby/intern.h1
-rw-r--r--io.c2
-rw-r--r--process.c2
-rw-r--r--thread.c35
5 files changed, 55 insertions, 3 deletions
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 <akr@fsij.org>
+
+ * 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 <matz@ruby-lang.org>
* 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;