Modify uncaught exception handler to call System.exit(1). 10/4110/4
authorTomas Olvecky <tolvecky@cisco.com>
Thu, 9 Jan 2014 12:29:49 +0000 (13:29 +0100)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 13 Jan 2014 11:48:29 +0000 (11:48 +0000)
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 <tolvecky@cisco.com>
Signed-off-by: Robert Varga <rovarga@cisco.com>
opendaylight/distribution/opendaylight/src/main/resources/configuration/logback.xml
opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/Activator.java
opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/UncaughtExceptionHandler.java [deleted file]
opendaylight/logging/bridge/src/main/java/org/opendaylight/controller/logging/bridge/internal/UncaughtExceptionPolicy.java [new file with mode: 0644]

index 84d1c913c413ef5e1978aded60ff85c200437169..61d274d80c22daf91dd28fe6cf8b9c7138fb7c41 100644 (file)
@@ -41,7 +41,8 @@
   <logger name="org.opendaylight.controller" level="INFO"/>
 
   <!-- OSGi logging bridge -->
-  <logger name="org.opendaylight.controller.logging.bridge" level="WARN"/>
+  <logger name="org.opendaylight.controller.logging.bridge" level="INFO"/>
+  <logger name="org.opendaylight.controller.logging.bridge.internal" level="WARN"/>
 
   <!-- Netty -->
   <logger name="io.netty" level="WARN"/>
index 95f57ae31cc405ec83b69e59a2fc3310be24848e..b231faf15307b558cebc629524ee185c12c89a97 100644 (file)
@@ -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 (file)
index 6fe9c44..0000000
+++ /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 (file)
index 0000000..0545578
--- /dev/null
@@ -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);
+}