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;
}

Reply via email to