Hi, I have been investigating why 'ant' hangs under GIJ when running external commands. The problem is in Process.waitFor(), which hangs because libgcj's ProcessManager thread never gets SIGCHLD. This can be reproduced with the attached Test.java.
It turns out it is a bug in the way glibc handles signal delivery. Apparently process-wide signals are only ever delivered to the main thread, regardless of the block masks. Furthermore, there seem to be another problem with delayed delivery, when a thread temporarily blocks a signal. Glibc waits until another signal is received before delivering the first one. I'm going to look into this further, but I wanted to report it and ask whether you have any advice as to how this should be fixed. The attached testsigthread.c can be used to reproduce these problem: Works as expected: $ ./testsigthread Unblocking now. *kill* Got it! Needs a second signal: $ ./testsigthread *kill* Unblocking now. *nothing happens, re-kill* Got it! Got it! Separate thread: $ ./testsigthread x Unblocking now. *kill* (hangs forever) $ ./testsigthread x *kill* Unblocking now. (hangs forever) -- Jeremie Koenig <j...@jk.fr.eu.org> http://jk.fr.eu.org
public class Test { public static void main(String args[]) throws Exception { Runtime.getRuntime().exec("true").waitFor(); } }
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/signal.h> #include <pthread.h> static sigset_t sigset; static void signal_handler(int sig) { printf("Got it!\n"); } static void *wait_for_signal(void *whatever) { signal(SIGUSR1, signal_handler); sleep(5); printf("Unblocking now.\n"); pthread_sigmask(SIG_UNBLOCK, &sigset, NULL); sleep(1000); return NULL; } static void w4s_other_thread(void) { pthread_t thread; pthread_create(&thread, NULL, wait_for_signal, NULL); pthread_join(thread, NULL); } int main(int argc, char **argv) { sigemptyset(&sigset); sigaddset(&sigset, SIGUSR1); pthread_sigmask(SIG_BLOCK, &sigset, NULL); if(argc > 1) w4s_other_thread(); else wait_for_signal(NULL); return 0; }