com.yahoo.yolean.system.CatchSignals Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vespajlib Show documentation
Show all versions of vespajlib Show documentation
Library for use in Java components of Vespa. Shared code which do
not fit anywhere else.
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.yolean.system;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.atomic.AtomicBoolean;
// import sun.misc.Signal;
// import sun.misc.SignalHandler;
public class CatchSignals {
/**
* Sets up a signal handler for SIGTERM and SIGINT, where a given AtomicBoolean
* gets a true value when the signal is caught.
*
* Callers basically have two options for acting on the signal:
*
* They may choose to synchronize and wait() on this variable,
* and they will be notified when it changes state to true. To avoid
* problems with spurious wakeups, use a while loop and wait()
* again if the state is still false. As soon as the caller has been
* woken up and the state is true, the application should exit as
* soon as possible.
*
* They may also choose to poll the state of this variable. As soon
* as its state becomes true, the signal has been received, and the
* application should exit as soon as possible.
*
* @param signalCaught set to false initially, will be set to true when SIGTERM or SIGINT is caught.
*/
@SuppressWarnings("rawtypes")
public static void setup(final AtomicBoolean signalCaught) {
signalCaught.set(false);
try {
Class shc = Class.forName("sun.misc.SignalHandler");
Class ssc = Class.forName("sun.misc.Signal");
InvocationHandler ihandler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
synchronized (signalCaught) {
signalCaught.set(true);
signalCaught.notifyAll();
}
return null;
}
};
Object shandler = Proxy.newProxyInstance(CatchSignals.class.getClassLoader(),
new Class[] { shc },
ihandler);
Constructor[] c = ssc.getDeclaredConstructors();
assert c.length == 1;
Object sigterm = c[0].newInstance("TERM");
Object sigint = c[0].newInstance("INT");
Method m = findMethod(ssc, "handle");
assert m != null; // "NoSuchMethodException"
m.invoke(null, sigterm, shandler);
m.invoke(null, sigint, shandler);
} catch (ClassNotFoundException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
System.err.println("FAILED setting up signal catching: "+e);
}
}
private static Method findMethod(Class> c, String name) {
for (Method m : c.getDeclaredMethods()) {
if (m.getName().equals(name)) {
return m;
}
}
return null;
}
}