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
+ }
+ }
+ }
}