From 40b650e0d9a2e007ebe4f8fabdef14864d6c24c7 Mon Sep 17 00:00:00 2001 From: Arne Juul Date: Tue, 21 Jun 2016 14:00:06 +0200 Subject: copy utility from vespajlib * this class will be used by jdisc_core but we want to avoid the classloader problems we got when jdisc_core used vespajlib directly, so copy it to this library that has fewer transitive dependencies. --- .../java/com/yahoo/yolean/system/CatchSigTerm.java | 69 ++++++++++++++++++++++ .../yahoo/yolean/system/CatchSigTermTestCase.java | 19 ++++++ 2 files changed, 88 insertions(+) create mode 100644 yolean/src/main/java/com/yahoo/yolean/system/CatchSigTerm.java create mode 100644 yolean/src/test/java/com/yahoo/yolean/system/CatchSigTermTestCase.java diff --git a/yolean/src/main/java/com/yahoo/yolean/system/CatchSigTerm.java b/yolean/src/main/java/com/yahoo/yolean/system/CatchSigTerm.java new file mode 100644 index 00000000000..204dcaacf28 --- /dev/null +++ b/yolean/src/main/java/com/yahoo/yolean/system/CatchSigTerm.java @@ -0,0 +1,69 @@ +// Copyright 2016 Yahoo Inc. 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.*; + +// import sun.misc.Signal; +// import sun.misc.SignalHandler; + +import java.util.concurrent.atomic.AtomicBoolean; + +public class CatchSigTerm { + /** + * Sets up a signal handler for SIGTERM, where a given AtomicBoolean + * gets a true value when the TERM signal is caught. + * + * Callers basically have two options for acting on the TERM 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 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(CatchSigTerm.class.getClassLoader(), + new Class[] { shc }, + ihandler); + Constructor[] c = ssc.getDeclaredConstructors(); + assert c.length == 1; + Object sigterm = c[0].newInstance("TERM"); + Method m = findMethod(ssc, "handle"); + assert m != null; // "NoSuchMethodException" + m.invoke(null, sigterm, 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; + } +} diff --git a/yolean/src/test/java/com/yahoo/yolean/system/CatchSigTermTestCase.java b/yolean/src/test/java/com/yahoo/yolean/system/CatchSigTermTestCase.java new file mode 100644 index 00000000000..d2ad84948e1 --- /dev/null +++ b/yolean/src/test/java/com/yahoo/yolean/system/CatchSigTermTestCase.java @@ -0,0 +1,19 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.yolean.system; + +import com.yahoo.yolean.system.CatchSigTerm; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * @author arnej27959 + */ +public class CatchSigTermTestCase extends junit.framework.TestCase { + + public CatchSigTermTestCase(String name) { + super(name); + } + + public void testThatSetupCompiles() { + CatchSigTerm.setup(new AtomicBoolean(false)); + } +} -- cgit v1.2.3