This is an automated email from the ASF dual-hosted git repository.

mmarshall pushed a commit to branch branch-2.10
in repository https://gitbox.apache.org/repos/asf/pulsar.git


The following commit(s) were added to refs/heads/branch-2.10 by this push:
     new 090d1b7719f [fix][fn] Exit JVM when main thread throws exception 
(#20689)
090d1b7719f is described below

commit 090d1b7719f0592fde9e97029bc2326984185c29
Author: Michael Marshall <[email protected]>
AuthorDate: Fri Jun 30 12:03:37 2023 -0500

    [fix][fn] Exit JVM when main thread throws exception (#20689)
    
    Fixes: https://github.com/apache/pulsar/issues/20688
    
    When a function throws an exception that ends processing, we should exit 
the JVM.
    
    * Update `JavaInstanceMain` so that an exception leads to exiting the JVM. 
Since the class does not use any dependencies (see the class's Javadoc), we use 
reflection to shutdown logging.
    
    This change is a trivial rework / code cleanup without any test coverage.
    
    - [x] `doc-not-needed`
    
    (cherry picked from commit d83c7a6cc16dd374a976d7d535b5fcd325b5a812)
---
 .../functions/instance/JavaInstanceMain.java       | 56 ++++++++++++++++++----
 1 file changed, 47 insertions(+), 9 deletions(-)

diff --git 
a/pulsar-functions/runtime-all/src/main/java/org/apache/pulsar/functions/instance/JavaInstanceMain.java
 
b/pulsar-functions/runtime-all/src/main/java/org/apache/pulsar/functions/instance/JavaInstanceMain.java
index 6852792d614..b3609964bd6 100644
--- 
a/pulsar-functions/runtime-all/src/main/java/org/apache/pulsar/functions/instance/JavaInstanceMain.java
+++ 
b/pulsar-functions/runtime-all/src/main/java/org/apache/pulsar/functions/instance/JavaInstanceMain.java
@@ -54,6 +54,20 @@ public class JavaInstanceMain {
 
     private static final String FUNCTIONS_INSTANCE_CLASSPATH = 
"pulsar.functions.instance.classpath";
 
+    private static final Method log4j2ShutdownMethod;
+
+    static {
+        // use reflection to find org.apache.logging.log4j.LogManager.shutdown 
method
+        Method shutdownMethod = null;
+        try {
+            shutdownMethod = 
Class.forName("org.apache.logging.log4j.LogManager")
+                    .getMethod("shutdown");
+        } catch (ClassNotFoundException | NoSuchMethodException e) {
+            // ignore
+        }
+        log4j2ShutdownMethod = shutdownMethod;
+    }
+
     public JavaInstanceMain() { }
 
     public static void main(String[] args) throws Exception {
@@ -89,15 +103,27 @@ public class JavaInstanceMain {
 
         System.out.println("Using function root classloader: " + root);
         System.out.println("Using function instance classloader: " + 
functionInstanceClsLoader);
-
-        // use the function instance classloader to create 
org.apache.pulsar.functions.runtime.JavaInstanceStarter
-        Object main = 
createInstance("org.apache.pulsar.functions.runtime.JavaInstanceStarter", 
functionInstanceClsLoader);
-
-        // Invoke start method of JavaInstanceStarter to start the function 
instance code
-        Method method = main.getClass().getDeclaredMethod("start", 
String[].class, ClassLoader.class, ClassLoader.class);
-
-        System.out.println("Starting function instance...");
-        method.invoke(main, args, functionInstanceClsLoader, root);
+        try {
+            // use the function instance classloader to create 
org.apache.pulsar.functions.runtime.JavaInstanceStarter
+            Object main =
+                    
createInstance("org.apache.pulsar.functions.runtime.JavaInstanceStarter",
+                            functionInstanceClsLoader);
+
+            // Invoke start method of JavaInstanceStarter to start the 
function instance code
+            Method method =
+                    main.getClass().getDeclaredMethod("start", String[].class, 
ClassLoader.class, ClassLoader.class);
+
+            System.out.println("Starting function instance...");
+            method.invoke(main, args, functionInstanceClsLoader, root);
+        } catch (Throwable e) {
+            try {
+                shutdownLogging();
+            } finally {
+                System.out.println("Failed to start function instance.");
+                e.printStackTrace();
+                Runtime.getRuntime().halt(1);
+            }
+        }
     }
 
     public static Object createInstance(String userClassName,
@@ -148,4 +174,16 @@ public class JavaInstanceMain {
             return true;
         }
     }
+
+    private static void shutdownLogging() {
+        // flush log buffers and shutdown log4j2 logging to prevent log 
truncation
+        if (log4j2ShutdownMethod != null) {
+            try {
+                // use reflection to call 
org.apache.logging.log4j.LogManager.shutdown()
+                log4j2ShutdownMethod.invoke(null);
+            } catch (IllegalAccessException | InvocationTargetException e) {
+                // ignore
+            }
+        }
+    }
 }

Reply via email to