Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/classlib/gnuclasspath/classlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ extern Thread *classlibJThread2Thread(Object *jThread);
extern void classlibThreadName2Buff(Object *jThread, char *buffer,
int buff_len);

extern void classlibInitialiseSignalMask();

#define classlibInitialiseSignals() \
/* NOTHING TO DO */ TRUE

Expand Down
14 changes: 14 additions & 0 deletions src/classlib/gnuclasspath/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,20 @@ void classlibThreadName2Buff(Object *jThread, char *buffer, int buff_len) {
String2Buff(name, buffer, buff_len);
}

/* SIGQUIT and SIGINT are received synchronously via sigwait(),
so they must be blocked in all threads. SIGPIPE is blocked
so writes to broken pipes fail with EPIPE. Process-spawning
code must clear the inherited mask before exec. */
void classlibInitialiseSignalMask() {
sigset_t mask;

sigemptyset(&mask);
sigaddset(&mask, SIGQUIT);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGPIPE);
sigprocmask(SIG_BLOCK, &mask, NULL);
}

void classlibSignalThread(Thread *self) {
sigset_t mask;
int sig;
Expand Down
1 change: 1 addition & 0 deletions src/classlib/openjdk/classlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ extern void classlibSetThreadState(Thread *thread, int state);
extern void classlibThreadName2Buff(Object *jThread, char *buffer,
int buff_len);

extern void classlibInitialiseSignalMask();
extern int classlibInitialiseSignals();
extern void classlibSignalThread(Thread *self);

Expand Down
45 changes: 42 additions & 3 deletions src/classlib/openjdk/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,43 @@ void classlibSignalThread(Thread *self) {
}
}

/* Signals are received via asynchronous handlers. Make sure all
signals the VM uses are unblocked, so they can be delivered to
the registered handlers. SIGQUIT and SIGPIPE are handled by
JamVM itself; SIGHUP, SIGINT and SIGTERM can be handled by the
class library via sun.misc.Signal, and are the only signals it
can register (see JVM_FindSignal) */
void classlibInitialiseSignalMask() {
sigset_t mask;

sigemptyset(&mask);
sigaddset(&mask, SIGQUIT);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGHUP);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGPIPE);
pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
}

/* Writes to broken pipes must fail with EPIPE rather than kill
the VM. Unlike blocking or SIG_IGN, a no-op handler is reset
to default on exec, so it doesn't leak into spawned children. */
static void pipeHandler(int sig) {
}

int classlibInitialiseSignals() {
struct sigaction act;
Class *signal_class;

act.sa_handler = signalHandler;
act.sa_handler = pipeHandler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
sigaction(SIGQUIT, &act, NULL);
sigaction(SIGPIPE, &act, NULL);

/*
* Initialise everything used by signalHandler before installing
* it, as these signals may already be unblocked.
*/
sem_init(&signal_sem, 0, 0);

signal_class = findSystemClass(SYMBOL(sun_misc_Signal));
Expand All @@ -222,6 +250,17 @@ int classlibInitialiseSignals() {

signal_dispatch_mb = findMethod(signal_class, SYMBOL(dispatch),
SYMBOL(_I__V));
if(signal_dispatch_mb == NULL)
return FALSE;

return signal_dispatch_mb != NULL;
act.sa_handler = signalHandler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;

sigaction(SIGQUIT, &act, NULL);
sigaction(SIGHUP, &act, NULL);
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);

return TRUE;
}
30 changes: 11 additions & 19 deletions src/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -761,8 +761,6 @@ void createJavaThread(Object *jThread, long long stack_size) {
enableSuspend(self);
}

static void initialiseSignalMask();

Thread *attachJNIThread(char *name, char is_daemon, Object *group) {
Thread *thread = sysMalloc(sizeof(Thread));
void *stack_base = nativeStackBase();
Expand All @@ -775,7 +773,7 @@ Thread *attachJNIThread(char *name, char is_daemon, Object *group) {
memset(thread, 0, sizeof(Thread));

/* Externally created threads will not inherit signal state */
initialiseSignalMask();
classlibInitialiseSignalMask();

/* Initialise the thread and add it to the VM thread list */
return attachThread(name, is_daemon, stack_base, thread, group);
Expand Down Expand Up @@ -1134,24 +1132,9 @@ void printThreadsDump(Thread *self) {
resumeAllThreads(self);
}

static void initialiseSignalMask() {
sigset_t mask;

sigemptyset(&mask);
sigaddset(&mask, SIGQUIT);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGPIPE);
sigprocmask(SIG_BLOCK, &mask, NULL);
}

static int initialiseSignals() {
struct sigaction act;

/* Initialise signal mask. Signal masks are per-thread,
but as this is the main thread it will be inherited
by all threads created wtihin Java */
initialiseSignalMask();

/* Setup signal handler for thread suspension. Signal
handlers are process-wide */

Expand All @@ -1161,7 +1144,16 @@ static int initialiseSignals() {
sigaction(SIGUSR1, &act, NULL);

/* Do classlib specific initialisation */
return classlibInitialiseSignals();
if(!classlibInitialiseSignals())
return FALSE;

/* Initialise signal mask, after the handlers have been
installed. Signal masks are per-thread, but as this is
the main thread it will be inherited by all threads
created wtihin Java */
classlibInitialiseSignalMask();

return TRUE;
}

/* garbage collection support */
Expand Down
Loading