From 3a9876cd3ff25063d6820b687be358296fc59156 Mon Sep 17 00:00:00 2001 From: Tomas Olvecky Date: Thu, 9 Jan 2014 13:29:49 +0100 Subject: [PATCH] Modify uncaught exception handler to call System.exit(1). This introduces the ability to specify how uncaught exceptions are handled via setting controller.uncaughtExceptionPolicy property. There are two policies: IGNORE and ABORT. The former logs which thread has died and does nothing else. The latter forces a virtual machine shutdown when a thread dies. The default policy is IGNORE, as that has been the historic setting. For Helium release, this should probably get discussed, as uncontrolled thread death may leave the controller in an inconsistent/invalid state. Change-Id: Ib7c64b23e1cd3c7c45cfa31401410bba22acd431 Signed-off-by: Tomas Olvecky Signed-off-by: Robert Varga --- .../main/resources/configuration/logback.xml | 3 +- .../logging/bridge/internal/Activator.java | 35 ++++++++++++++----- .../internal/UncaughtExceptionHandler.java | 13 ------- .../internal/UncaughtExceptionPolicy.java | 31 ++++++++++++++++ 4 files changed, 59 insertions(+), 23 deletions(-) delete mode 100644 opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/UncaughtExceptionHandler.java create mode 100644 opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/UncaughtExceptionPolicy.java diff --git a/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml b/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml index 84d1c913c4..61d274d80c 100644 --- a/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml +++ b/opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml @@ -41,7 +41,8 @@ - + + diff --git a/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java index 95f57ae31c..b231faf153 100644 --- a/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java +++ b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * @@ -6,11 +5,13 @@ * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ - package org.opendaylight.controller.logging.bridge.internal; import org.osgi.service.log.LogEntry; + +import java.lang.Thread.UncaughtExceptionHandler; import java.util.Enumeration; + import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.BundleActivator; @@ -21,7 +22,11 @@ import org.slf4j.ILoggerFactory; import org.osgi.service.log.LogReaderService; public class Activator implements BundleActivator { + private static final String UNCAUGHT_EXCEPTION_POLICY_PROP = "controller.uncaughtExceptionPolicy"; + private static final UncaughtExceptionPolicy DEFAULT_UNCAUGHT_EXCEPTION_POLICY = UncaughtExceptionPolicy.IGNORE; + private LogListenerImpl listener = null; + private ShutdownHandler shutdownHandler = null; private Logger log = null; @Override @@ -62,16 +67,25 @@ public class Activator implements BundleActivator { * handler will display the exceptions to OSGI console as well * as log to file. */ - Thread.setDefaultUncaughtExceptionHandler(new org.opendaylight. - controller.logging.bridge.internal.UncaughtExceptionHandler()); + UncaughtExceptionHandler handler = DEFAULT_UNCAUGHT_EXCEPTION_POLICY; + final String policy = context.getProperty(UNCAUGHT_EXCEPTION_POLICY_PROP); + if (policy != null) { + try { + handler = UncaughtExceptionPolicy.valueOf(policy.toUpperCase()); + } catch (IllegalArgumentException ex) { + log.warn("Invalid policy name \"{}\", defaulting to {}", policy, handler); + } + } + log.info("Setting uncaught exception policy to {}", handler); + Thread.setDefaultUncaughtExceptionHandler(handler); /* * Install the Shutdown handler. This will intercept SIGTERM signal and * close the system bundle. This allows for a graceful closing of OSGI * framework. */ - - Runtime.getRuntime().addShutdownHook(new shutdownHandler(context)); + shutdownHandler = new ShutdownHandler(context); + Runtime.getRuntime().addShutdownHook(shutdownHandler); } else { this.log.error("Cannot register the LogListener because " + "cannot retrieve LogReaderService"); @@ -90,14 +104,17 @@ public class Activator implements BundleActivator { LogReaderService reader = (LogReaderService) service; reader.removeLogListener(this.listener); } - + if (this.shutdownHandler != null) { + Runtime.getRuntime().removeShutdownHook(this.shutdownHandler); + } this.listener = null; this.log = null; + this.shutdownHandler = null; } - private class shutdownHandler extends Thread { + private class ShutdownHandler extends Thread { BundleContext bundlecontext; - public shutdownHandler(BundleContext ctxt) { + public ShutdownHandler(BundleContext ctxt) { this.bundlecontext = ctxt; } diff --git a/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/UncaughtExceptionHandler.java b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/UncaughtExceptionHandler.java deleted file mode 100644 index 6fe9c4441f..0000000000 --- a/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/UncaughtExceptionHandler.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.opendaylight.controller.logging.bridge.internal; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -public class UncaughtExceptionHandler implements Thread.UncaughtExceptionHandler{ - private static Logger log = LoggerFactory.getLogger(UncaughtExceptionHandler.class); - - public void uncaughtException (Thread t, Throwable e) { - log.error("Uncaught ExceptionHandler:", e); - } -} diff --git a/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/UncaughtExceptionPolicy.java b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/UncaughtExceptionPolicy.java new file mode 100644 index 0000000000..0545578b7f --- /dev/null +++ b/opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/UncaughtExceptionPolicy.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.controller.logging.bridge.internal; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +enum UncaughtExceptionPolicy implements Thread.UncaughtExceptionHandler { + ABORT { + public static final int EXIT_CODE = 1; + + @Override + public void uncaughtException(final Thread t, final Throwable e) { + log.error("Thread {} died because of an uncaught exception, forcing virtual machine shutdown", t, e); + System.exit(EXIT_CODE); + } + }, + IGNORE { + @Override + public void uncaughtException(final Thread t, final Throwable e) { + log.error("Thread {} died because of an uncaught exception", t, e); + } + }; + + private static final Logger log = LoggerFactory.getLogger(UncaughtExceptionPolicy.class); +} -- 2.36.6