Whipped up some native code to allow signals to be caught and handled from
within Java (on Linux anyway). We dig it the most baby! git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2360 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# $Id: Makefile,v 1.4 2003/02/18 23:06:54 ray Exp $
|
# $Id: Makefile,v 1.5 2003/03/31 02:10:04 mdb Exp $
|
||||||
|
|
||||||
#
|
#
|
||||||
# Executable definitions
|
# Executable definitions
|
||||||
@@ -30,10 +30,12 @@ INSTALL_TARGET=${INSTALL_PATH}/${TARGET}
|
|||||||
all: ${INSTALL_TARGET}
|
all: ${INSTALL_TARGET}
|
||||||
|
|
||||||
${INSTALL_TARGET}: com_threerings_util_keybd_Keyboard.c
|
${INSTALL_TARGET}: com_threerings_util_keybd_Keyboard.c
|
||||||
${CC} ${INCLUDES} -c com_threerings_util_keybd_Keyboard.c \
|
@echo Compiling Keyboard.c
|
||||||
|
@${CC} ${INCLUDES} -c com_threerings_util_keybd_Keyboard.c \
|
||||||
-o com_threerings_util_keybd_Keyboard.o
|
-o com_threerings_util_keybd_Keyboard.o
|
||||||
${MKDIR} -p ${INSTALL_PATH}
|
@echo Creating libkeybd.so
|
||||||
${CC} -o ${INSTALL_TARGET} com_threerings_util_keybd_Keyboard.o \
|
@${MKDIR} -p ${INSTALL_PATH}
|
||||||
|
@${CC} -o ${INSTALL_TARGET} com_threerings_util_keybd_Keyboard.o \
|
||||||
${LIBRARIES} ${LIBRARIES_PATH} -shared
|
${LIBRARIES} ${LIBRARIES_PATH} -shared
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
@@ -0,0 +1,261 @@
|
|||||||
|
//
|
||||||
|
// $Id: SignalManager.java,v 1.1 2003/03/31 02:10:04 mdb Exp $
|
||||||
|
|
||||||
|
package com.threerings.util.signal;
|
||||||
|
|
||||||
|
import com.samskivert.util.HashIntMap;
|
||||||
|
import com.samskivert.util.ObserverList;
|
||||||
|
import com.threerings.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses native code to catch Unix signals and invoke callbacks on a
|
||||||
|
* separate signal handler thread. If the native library cannot be loaded,
|
||||||
|
* signal handlers will be allowed to be registered but will never be
|
||||||
|
* called.
|
||||||
|
*/
|
||||||
|
public class SignalManager
|
||||||
|
{
|
||||||
|
/* Hangup (POSIX). */
|
||||||
|
public static final int SIGHUP = 1;
|
||||||
|
|
||||||
|
/* Interrupt (ANSI). */
|
||||||
|
public static final int SIGINT = 2;
|
||||||
|
|
||||||
|
/* Quit (POSIX). */
|
||||||
|
public static final int SIGQUIT = 3;
|
||||||
|
|
||||||
|
/* Illegal instruction (ANSI). */
|
||||||
|
public static final int SIGILL = 4;
|
||||||
|
|
||||||
|
/* Trace trap (POSIX). */
|
||||||
|
public static final int SIGTRAP = 5;
|
||||||
|
|
||||||
|
/* Abort (ANSI). */
|
||||||
|
public static final int SIGABRT = 6;
|
||||||
|
|
||||||
|
/* IOT trap (4.2 BSD). */
|
||||||
|
public static final int SIGIOT = 6;
|
||||||
|
|
||||||
|
/* BUS error (4.2 BSD). */
|
||||||
|
public static final int SIGBUS = 7;
|
||||||
|
|
||||||
|
/* Floating-point exception (ANSI). */
|
||||||
|
public static final int SIGFPE = 8;
|
||||||
|
|
||||||
|
/* Kill, unblockable (POSIX). */
|
||||||
|
public static final int SIGKILL = 9;
|
||||||
|
|
||||||
|
/* User-defined signal 1 (POSIX). */
|
||||||
|
public static final int SIGUSR1 = 10;
|
||||||
|
|
||||||
|
/* Segmentation violation (ANSI). */
|
||||||
|
public static final int SIGSEGV = 11;
|
||||||
|
|
||||||
|
/* User-defined signal 2 (POSIX). */
|
||||||
|
public static final int SIGUSR2 = 12;
|
||||||
|
|
||||||
|
/* Broken pipe (POSIX). */
|
||||||
|
public static final int SIGPIPE = 13;
|
||||||
|
|
||||||
|
/* Alarm clock (POSIX). */
|
||||||
|
public static final int SIGALRM = 14;
|
||||||
|
|
||||||
|
/* Termination (ANSI). */
|
||||||
|
public static final int SIGTERM = 15;
|
||||||
|
|
||||||
|
/* Stack fault. */
|
||||||
|
public static final int SIGSTKFLT = 16;
|
||||||
|
|
||||||
|
/* Child status has changed (POSIX). */
|
||||||
|
public static final int SIGCHLD = 17;
|
||||||
|
|
||||||
|
/* Continue (POSIX). */
|
||||||
|
public static final int SIGCONT = 18;
|
||||||
|
|
||||||
|
/* Stop, unblockable (POSIX). */
|
||||||
|
public static final int SIGSTOP = 19;
|
||||||
|
|
||||||
|
/* Keyboard stop (POSIX). */
|
||||||
|
public static final int SIGTSTP = 20;
|
||||||
|
|
||||||
|
/* Background read from tty (POSIX). */
|
||||||
|
public static final int SIGTTIN = 21;
|
||||||
|
|
||||||
|
/* Background write to tty (POSIX). */
|
||||||
|
public static final int SIGTTOU = 22;
|
||||||
|
|
||||||
|
/* Urgent condition on socket (4.2 BSD). */
|
||||||
|
public static final int SIGURG = 23;
|
||||||
|
|
||||||
|
/* CPU limit exceeded (4.2 BSD). */
|
||||||
|
public static final int SIGXCPU = 24;
|
||||||
|
|
||||||
|
/* File size limit exceeded (4.2 BSD). */
|
||||||
|
public static final int SIGXFSZ = 25;
|
||||||
|
|
||||||
|
/* Virtual alarm clock (4.2 BSD). */
|
||||||
|
public static final int SIGVTALRM = 26;
|
||||||
|
|
||||||
|
/* Profiling alarm clock (4.2 BSD). */
|
||||||
|
public static final int SIGPROF = 27;
|
||||||
|
|
||||||
|
/* Window size change (4.3 BSD, Sun). */
|
||||||
|
public static final int SIGWINCH = 28;
|
||||||
|
|
||||||
|
/* I/O now possible (4.2 BSD). */
|
||||||
|
public static final int SIGIO = 29;
|
||||||
|
|
||||||
|
/* Pollable event occurred (System V). */
|
||||||
|
public static final int SIGPOLL = SIGIO;
|
||||||
|
|
||||||
|
/* Power failure restart (System V). */
|
||||||
|
public static final int SIGPWR = 30;
|
||||||
|
|
||||||
|
/* Bad system call. */
|
||||||
|
public static final int SIGSYS = 31;
|
||||||
|
|
||||||
|
/** Used to dispatch signal notifications. */
|
||||||
|
public static interface SignalHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called when the specified signal is received.
|
||||||
|
*
|
||||||
|
* @return true if the signal handler should remain registered,
|
||||||
|
* false if it should be removed.
|
||||||
|
*/
|
||||||
|
public boolean signalReceived (int signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if signal dispatching services are available, false if
|
||||||
|
* we could not load our native library.
|
||||||
|
*/
|
||||||
|
public boolean servicesAvailable ()
|
||||||
|
{
|
||||||
|
return _haveLibrary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a signal handler for the specified signal.
|
||||||
|
*/
|
||||||
|
public synchronized static void registerSignalHandler (
|
||||||
|
int signal, SignalHandler handler)
|
||||||
|
{
|
||||||
|
ObserverList list = (ObserverList)_handlers.get(signal);
|
||||||
|
if (list == null) {
|
||||||
|
_handlers.put(signal, list = new ObserverList(
|
||||||
|
ObserverList.SAFE_IN_ORDER_NOTIFY));
|
||||||
|
if (_haveLibrary) {
|
||||||
|
activateHandler(signal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list.add(handler);
|
||||||
|
|
||||||
|
// make sure the signal dispatcher thread is started
|
||||||
|
if (_haveLibrary && _sigdis == null) {
|
||||||
|
_sigdis = new Thread() {
|
||||||
|
public void run () {
|
||||||
|
Log.info("Dispatching signals...");
|
||||||
|
dispatchSignals();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_sigdis.setDaemon(true);
|
||||||
|
_sigdis.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the registration for the specified signal handler.
|
||||||
|
*/
|
||||||
|
public synchronized static void removeSignalHandler (
|
||||||
|
int signal, SignalHandler handler)
|
||||||
|
{
|
||||||
|
ObserverList list = (ObserverList)_handlers.get(signal);
|
||||||
|
if (list == null || !list.contains(handler)) {
|
||||||
|
Log.warning("Requested to remove non-registered handler " +
|
||||||
|
"[signal=" + signal + ", handler=" + handler + "].");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
list.remove(handler);
|
||||||
|
checkEmpty(signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called by native code when a signal is received.
|
||||||
|
*/
|
||||||
|
protected synchronized static void signalReceived (final int signal)
|
||||||
|
{
|
||||||
|
// this is hack, but we seem to get a call to our signal handler
|
||||||
|
// for each thread if the user presses ctrl-c in the terminal, so
|
||||||
|
// we "collapse" those into one call back
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
if (signal == SIGINT) {
|
||||||
|
if (_lastINTed == now) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
_lastINTed = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ObserverList list = (ObserverList)_handlers.get(signal);
|
||||||
|
if (list != null) {
|
||||||
|
list.apply(new ObserverList.ObserverOp() {
|
||||||
|
public boolean apply (Object obs) {
|
||||||
|
return ((SignalHandler)obs).signalReceived(signal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
checkEmpty(signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a signal handler is removed.
|
||||||
|
*/
|
||||||
|
protected static void checkEmpty (int signal)
|
||||||
|
{
|
||||||
|
ObserverList list = (ObserverList)_handlers.get(signal);
|
||||||
|
if (list != null && list.size() == 0) {
|
||||||
|
_handlers.remove(signal);
|
||||||
|
if (_haveLibrary) {
|
||||||
|
deactivateHandler(signal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates the signal handler for the specified signal.
|
||||||
|
*/
|
||||||
|
protected static native void activateHandler (int signal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deactivates the signal handler for the specified signal.
|
||||||
|
*/
|
||||||
|
protected static native void deactivateHandler (int signal);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consigns a Java thread to the task of dispatching signal handler
|
||||||
|
* callbacks.
|
||||||
|
*/
|
||||||
|
protected static native void dispatchSignals ();
|
||||||
|
|
||||||
|
/** A mapping from signal number to a list of handlers. */
|
||||||
|
protected static HashIntMap _handlers = new HashIntMap();
|
||||||
|
|
||||||
|
/** Our signal dispatcher thread. */
|
||||||
|
protected static Thread _sigdis;
|
||||||
|
|
||||||
|
/** Set to true if we successfully load our native library. */
|
||||||
|
protected static boolean _haveLibrary;
|
||||||
|
|
||||||
|
/** Used to collapse bogus multiple delivery of SIGINT when the user
|
||||||
|
* pressed ctrl-c in the console. */
|
||||||
|
protected static long _lastINTed = 0L;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("signal");
|
||||||
|
_haveLibrary = true;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.info("Could not load libsignal.so; signal handling disabled.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||||
|
#include <jni.h>
|
||||||
|
/* Header for class com_threerings_util_signal_SignalManager */
|
||||||
|
|
||||||
|
#ifndef _Included_com_threerings_util_signal_SignalManager
|
||||||
|
#define _Included_com_threerings_util_signal_SignalManager
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGHUP
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGHUP 1L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGINT
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGINT 2L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGQUIT
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGQUIT 3L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGILL
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGILL 4L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGTRAP
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGTRAP 5L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGABRT
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGABRT 6L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGIOT
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGIOT 6L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGBUS
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGBUS 7L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGFPE
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGFPE 8L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGKILL
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGKILL 9L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGUSR1
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGUSR1 10L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGSEGV
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGSEGV 11L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGUSR2
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGUSR2 12L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGPIPE
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGPIPE 13L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGALRM
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGALRM 14L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGTERM
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGTERM 15L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGSTKFLT
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGSTKFLT 16L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGCHLD
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGCHLD 17L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGCONT
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGCONT 18L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGSTOP
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGSTOP 19L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGTSTP
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGTSTP 20L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGTTIN
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGTTIN 21L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGTTOU
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGTTOU 22L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGURG
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGURG 23L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGXCPU
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGXCPU 24L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGXFSZ
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGXFSZ 25L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGVTALRM
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGVTALRM 26L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGPROF
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGPROF 27L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGWINCH
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGWINCH 28L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGIO
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGIO 29L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGPOLL
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGPOLL 29L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGPWR
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGPWR 30L
|
||||||
|
#undef com_threerings_util_signal_SignalManager_SIGSYS
|
||||||
|
#define com_threerings_util_signal_SignalManager_SIGSYS 31L
|
||||||
|
/* Inaccessible static: _handlers */
|
||||||
|
/*
|
||||||
|
* Class: com_threerings_util_signal_SignalManager
|
||||||
|
* Method: activateHandler
|
||||||
|
* Signature: (I)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_threerings_util_signal_SignalManager_activateHandler
|
||||||
|
(JNIEnv *, jclass, jint);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_threerings_util_signal_SignalManager
|
||||||
|
* Method: deactivateHandler
|
||||||
|
* Signature: (I)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_threerings_util_signal_SignalManager_deactivateHandler
|
||||||
|
(JNIEnv *, jclass, jint);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_threerings_util_signal_SignalManager
|
||||||
|
* Method: dispatchSignals
|
||||||
|
* Signature: ()V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_com_threerings_util_signal_SignalManager_dispatchSignals
|
||||||
|
(JNIEnv *, jclass);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#
|
||||||
|
# $Id: Makefile,v 1.1 2003/03/31 02:10:04 mdb Exp $
|
||||||
|
|
||||||
|
#
|
||||||
|
# Executable definitions
|
||||||
|
|
||||||
|
CC=gcc
|
||||||
|
RM=rm
|
||||||
|
CP=cp
|
||||||
|
MKDIR=mkdir
|
||||||
|
|
||||||
|
#
|
||||||
|
# Directory definitions
|
||||||
|
|
||||||
|
ROOT=../../../../../../..
|
||||||
|
LIBRARIES_PATH=
|
||||||
|
INSTALL_PATH=${ROOT}/dist/lib/i686-Linux
|
||||||
|
|
||||||
|
#
|
||||||
|
# Parameter and file definitions
|
||||||
|
|
||||||
|
INCLUDES=-I.. -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux
|
||||||
|
LIBRARIES=
|
||||||
|
TARGET=libsignal.so
|
||||||
|
INSTALL_TARGET=${INSTALL_PATH}/${TARGET}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Target definitions
|
||||||
|
|
||||||
|
all: ${INSTALL_TARGET}
|
||||||
|
|
||||||
|
${INSTALL_TARGET}: com_threerings_util_signal_SignalManager.c
|
||||||
|
@echo Compiling SignalManager.c
|
||||||
|
@${CC} ${INCLUDES} -c com_threerings_util_signal_SignalManager.c \
|
||||||
|
-o com_threerings_util_signal_SignalManager.o
|
||||||
|
@echo Creating libsignal.so
|
||||||
|
@${MKDIR} -p ${INSTALL_PATH}
|
||||||
|
@${CC} -o ${INSTALL_TARGET} com_threerings_util_signal_SignalManager.o \
|
||||||
|
${LIBRARIES} ${LIBRARIES_PATH} -shared
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-${RM} *.o
|
||||||
|
-${RM} ${INSTALL_TARGET}
|
||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* $Id: com_threerings_util_signal_SignalManager.c,v 1.1 2003/03/31 02:10:04 mdb Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <jni.h>
|
||||||
|
#include "com_threerings_util_signal_SignalManager.h"
|
||||||
|
|
||||||
|
static int writefd;
|
||||||
|
|
||||||
|
typedef void (*sighandler_t)(int);
|
||||||
|
static sighandler_t old_handlers[64];
|
||||||
|
static sighandler_t handlers[64];
|
||||||
|
|
||||||
|
static void
|
||||||
|
signal_handler (int signo)
|
||||||
|
{
|
||||||
|
write(writefd, &signo, sizeof(signo));
|
||||||
|
signal(SIGINT, signal_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class: com_threerings_util_signal_SignalManager
|
||||||
|
* Method: activateHandler
|
||||||
|
* Signature: (I)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_threerings_util_signal_SignalManager_activateHandler (
|
||||||
|
JNIEnv* env, jclass clazz, jint signo)
|
||||||
|
{
|
||||||
|
old_handlers[signo] = signal(signo, signal_handler);
|
||||||
|
if (old_handlers[signo] == SIG_ERR) {
|
||||||
|
fprintf(stderr, "Error setting signal handler (%d): %s\n",
|
||||||
|
signo, strerror(errno));
|
||||||
|
old_handlers[signo] = 0;
|
||||||
|
} else {
|
||||||
|
handlers[signo] = signal_handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class: com_threerings_util_signal_SignalManager
|
||||||
|
* Method: deactivateHandler
|
||||||
|
* Signature: (I)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_threerings_util_signal_SignalManager_deactivateHandler (
|
||||||
|
JNIEnv* env, jclass clazz, jint signo)
|
||||||
|
{
|
||||||
|
if (old_handlers[signo] != 0) {
|
||||||
|
signal(signo, old_handlers[signo]);
|
||||||
|
old_handlers[signo] = 0;
|
||||||
|
handlers[signo] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class: com_threerings_util_signal_SignalManager
|
||||||
|
* Method: dispatchSignals
|
||||||
|
* Signature: ()V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL
|
||||||
|
Java_com_threerings_util_signal_SignalManager_dispatchSignals (
|
||||||
|
JNIEnv* env, jclass clazz)
|
||||||
|
{
|
||||||
|
int filedes[2], readfd;
|
||||||
|
jint signo;
|
||||||
|
jmethodID mid = (*env)->GetStaticMethodID(
|
||||||
|
env, clazz, "signalReceived", "(I)V");
|
||||||
|
|
||||||
|
if (pipe(filedes) < 0) {
|
||||||
|
fprintf(stderr, "Failed to create signal pipe: %s\n", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
readfd = filedes[0];
|
||||||
|
writefd = filedes[1];
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
int got = read(readfd, &signo, sizeof(int));
|
||||||
|
if (got < 0) {
|
||||||
|
fprintf(stderr, "Signal pipe read failed: %s\n", strerror(errno));
|
||||||
|
} else if (got == 0) {
|
||||||
|
fprintf(stderr, "Signal pipe read returned zero bytes.\n");
|
||||||
|
} else {
|
||||||
|
if (signo < 0 || signo >= 64 || handlers[signo] == 0) {
|
||||||
|
fprintf(stderr, "Received bogus signal (%d).\n", signo);
|
||||||
|
} else {
|
||||||
|
(*env)->CallStaticVoidMethod(env, clazz, mid, signo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user