From c2003ab56b39c370678d7f6fe0b7fd3d8a7d0be8 Mon Sep 17 00:00:00 2001 From: Aaron Myers Date: Fri, 15 Mar 2013 21:16:41 +0000 Subject: [PATCH] HADOOP-9318. When exiting on a signal, print the signal name first. Contributed by Colin Patrick McCabe. git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1457122 13f79535-47bb-0310-9956-ffa450edef68 --- dev-support/test-patch.sh | 4 +- .../hadoop-common/CHANGES.txt | 3 + .../org/apache/hadoop/util/SignalLogger.java | 93 +++++++++++++++++++ .../org/apache/hadoop/util/StringUtils.java | 8 ++ .../apache/hadoop/util/TestSignalLogger.java | 42 +++++++++ 5 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/SignalLogger.java create mode 100644 hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestSignalLogger.java diff --git a/dev-support/test-patch.sh b/dev-support/test-patch.sh index 752f06cea3..c3d89aae01 100755 --- a/dev-support/test-patch.sh +++ b/dev-support/test-patch.sh @@ -436,8 +436,8 @@ checkJavadocWarnings () { echo "" echo "There appear to be $javadocWarnings javadoc warnings generated by the patched build." - #There are 6 warnings that are caused by things that are caused by using sun internal APIs. - OK_JAVADOC_WARNINGS=6; + #There are 11 warnings that are caused by things that are caused by using sun internal APIs. + OK_JAVADOC_WARNINGS=11; ### if current warnings greater than OK_JAVADOC_WARNINGS if [[ $javadocWarnings -ne $OK_JAVADOC_WARNINGS ]] ; then JIRA_COMMENT="$JIRA_COMMENT diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 61eb028581..1cb8ecbd3b 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -511,6 +511,9 @@ Release 2.0.5-beta - UNRELEASED HADOOP-9343. Allow additional exceptions through the RPC layer. (sseth) + HADOOP-9318. When exiting on a signal, print the signal name first. (Colin + Patrick McCabe via atm) + OPTIMIZATIONS BUG FIXES diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/SignalLogger.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/SignalLogger.java new file mode 100644 index 0000000000..c8667386fe --- /dev/null +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/SignalLogger.java @@ -0,0 +1,93 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.util; + +import sun.misc.Signal; +import sun.misc.SignalHandler; + +import org.apache.commons.logging.Log; +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.classification.InterfaceStability; + +/** + * This class logs a message whenever we're about to exit on a UNIX signal. + * This is helpful for determining the root cause of a process' exit. + * For example, if the process exited because the system administrator + * ran a standard "kill," you would see 'EXITING ON SIGNAL SIGTERM' in the log. + */ +@InterfaceAudience.Private +@InterfaceStability.Unstable +public enum SignalLogger { + INSTANCE; + + private boolean registered = false; + + /** + * Our signal handler. + */ + private static class Handler implements SignalHandler { + final private org.apache.commons.logging.Log LOG; + final private SignalHandler prevHandler; + + Handler(String name, Log LOG) { + this.LOG = LOG; + prevHandler = Signal.handle(new Signal(name), this); + } + + /** + * Handle an incoming signal. + * + * @param signal The incoming signal + */ + @Override + public void handle(Signal signal) { + LOG.error("RECEIVED SIGNAL " + signal.getNumber() + + ": SIG" + signal.getName()); + prevHandler.handle(signal); + } + } + + /** + * Register some signal handlers. + * + * @param LOG The log4j logfile to use in the signal handlers. + */ + public void register(final Log LOG) { + if (registered) { + throw new IllegalStateException("Can't re-install the signal handlers."); + } + registered = true; + StringBuilder bld = new StringBuilder(); + bld.append("registered UNIX signal handlers for ["); + final String SIGNALS[] = { "TERM", "HUP", "INT" }; + String separator = ""; + for (String signalName : SIGNALS) { + try { + new Handler(signalName, LOG); + bld.append(separator); + bld.append(signalName); + separator = ", "; + } catch (Exception e) { + LOG.debug(e); + } + } + bld.append("]"); + LOG.info(bld.toString()); + } +} diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringUtils.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringUtils.java index f2591f8104..e57d53c70f 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringUtils.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/StringUtils.java @@ -35,6 +35,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.lang.SystemUtils; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.fs.Path; @@ -613,6 +614,13 @@ public static void startupShutdownMessage(Class clazz, String[] args, ) ); + if (SystemUtils.IS_OS_UNIX) { + try { + SignalLogger.INSTANCE.register(LOG); + } catch (Throwable t) { + LOG.warn("failed to register any UNIX signal loggers: ", t); + } + } ShutdownHookManager.get().addShutdownHook( new Runnable() { @Override diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestSignalLogger.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestSignalLogger.java new file mode 100644 index 0000000000..73323eaa7a --- /dev/null +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/util/TestSignalLogger.java @@ -0,0 +1,42 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hadoop.util; + +import org.apache.commons.lang.SystemUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +public class TestSignalLogger { + public static final Log LOG = LogFactory.getLog(TestSignalLogger.class); + + @Test(timeout=60000) + public void testInstall() throws Exception { + Assume.assumeTrue(SystemUtils.IS_OS_UNIX); + SignalLogger.INSTANCE.register(LOG); + try { + SignalLogger.INSTANCE.register(LOG); + Assert.fail("expected IllegalStateException from double registration"); + } catch (IllegalStateException e) { + // fall through + } + } +}