(the short version - the parent forks and waitpids, and never gets a
SIGCHLD or a return from waitpid. This appears to be because the child
never exec's after the fork).
Please could test patches from my previous mails:
Date: Fri, 6 Aug 2010 13:31:14 +0200 (CEST)
Date: Fri, 6 Aug 2010 18:45:06 +0200 (CEST)
* 1.8.7.299-2 + rb18.diff
* 1.8.7.299-2 + rb18.diff + disabled 100730_disable_getsetcontext_on_nptl in
series
* 1.8.7.299-2 + rb18.diff + rb18-extra.diff
* 1.8.7.299-2 + rb18.diff + rb18-extra.diff + disabled
100730_disable_getsetcontext_on_nptl in debian/patches/series
rb18-extra.diff slightly alteres timer thread starting/ending,
it uses less pthread primitives (no pthread_cond),
the drawback is that ending of timer thread is not immediate,
but it might last at most 10ms.
Please send me detailed recipe, i.e. whole .rb file
and script which have to be run. While I looked into ruby implementation,
I do not speak ruby itself :-(
In the provided kdump, the child calls rfork,
in linux it is named clone. The rest of child dump
looks like thread manager, it is needed to also know
trace of 77777.
77775 ruby1.8 CALL sigprocmask(SIG_SETMASK,0xbfbe3af0,0xbfbe3af0)
77775 ruby1.8 RET sigprocmask 0
77775 ruby1.8 CALL rfork(RFPROC|RFMEM|RFTHREAD|RFSIGSHARE|RFLINUXTHPN)
77775 ruby1.8 RET rfork 77777/0x12fd1
77775 ruby1.8 CALL sigprocmask(SIG_SETMASK,0xbfbe3af0,0)
77775 ruby1.8 RET sigprocmask 0
I believe that following part of rb18.diff might help:
--- ruby1.8-1.8.7.299.orig/process.c
+++ ruby1.8-1.8.7.299/process.c
@@ -1332,13 +1332,11 @@
before_exec();
pid = fork();
- after_exec();
+ if (pid != 0)
+ after_exec();
switch (pid) {
case 0:
-#ifdef linux
- after_exec();
-#endif
rb_thread_atfork();
if (rb_block_given_p()) {
int status;
Petr
--- ruby1.8-1.8.7.299.orig/process.c
+++ ruby1.8-1.8.7.299/process.c
@@ -1332,13 +1332,11 @@
before_exec();
pid = fork();
- after_exec();
+ if (pid != 0)
+ after_exec();
switch (pid) {
case 0:
-#ifdef linux
- after_exec();
-#endif
rb_thread_atfork();
if (rb_block_given_p()) {
int status;
--- ruby1.8-1.8.7.299.orig/signal.c
+++ ruby1.8-1.8.7.299/signal.c
@@ -21,6 +21,7 @@
#undef SIGBUS
#endif
+#define sigprocmask pthread_sigmask
#if defined HAVE_SIGPROCMASK || defined HAVE_SIGSETMASK
#define USE_TRAP_MASK 1
#else
--- eval.STD 2010-06-10 06:38:43.000000000 +0200
+++ eval.c 2010-08-06 14:47:58.000000000 +0200
@@ -12317,6 +12317,7 @@
sigfillset(&all_signals);
pthread_sigmask(SIG_BLOCK, &all_signals, 0);
+#if 0
safe_mutex_lock(&running->lock);
pthread_cond_signal(start);
@@ -12325,6 +12326,13 @@
while ((err = WAIT_FOR_10MS()) == EINTR || err == ETIMEDOUT) {
if (timer_stopping)
break;
+#else
+ while (!timer_stopping)
+ {
+ to.tv_sec = 0;
+ to.tv_nsec = PER_NANO/100;
+ nanosleep(&to, NULL);
+#endif
if (!rb_thread_critical) {
rb_thread_pending = 1;
@@ -12334,7 +12342,9 @@
}
}
+#if 0
pthread_cleanup_pop(1);
+#endif
return NULL;
}
@@ -12342,6 +12352,7 @@
void
rb_thread_start_timer()
{
+#if 0
void *args[2];
static pthread_cond_t start = PTHREAD_COND_INITIALIZER;
@@ -12356,17 +12367,31 @@
pthread_cond_wait(&start, &time_thread.lock);
}
pthread_cleanup_pop(1);
+#else
+ if (rb_thread_alone()) return;
+ if (!__sync_bool_compare_and_swap (&thread_init, 0, 1))
+ return;
+ CATCH_VTALRM();
+
+ if (pthread_create(&time_thread.thread, 0, thread_timer, 0) != 0)
+ thread_init = 0;
+#endif
}
void
rb_thread_stop_timer()
{
if (!thread_init) return;
+#if 0
safe_mutex_lock(&time_thread.lock);
timer_stopping = 1;
pthread_cond_signal(&time_thread.cond);
thread_init = 0;
pthread_cleanup_pop(1);
+#else
+ timer_stopping = 1;
+ thread_init = 0;
+#endif
pthread_join(time_thread.thread, NULL);
timer_stopping = 0;
}