Skip to content

Commit 805c887

Browse files
committed
Add exception handling to atexit runner
1 parent 5ea5ad8 commit 805c887

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_atexit.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_clear
44
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_exit
55
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_order
6+
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_raise
67
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_unregister
78
*graalpython.lib-python.3.test.test_atexit.SubinterpreterTest.test_callback_on_subinterpreter_teardown
89
*graalpython.lib-python.3.test.test_atexit.SubinterpreterTest.test_callbacks_leak

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/AtexitModuleBuiltins.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,11 @@ int get() {
150150
abstract static class RunExitfuncsNode extends PythonBuiltinNode {
151151
@Specialization
152152
Object run() {
153-
getContext().runAtexitHooks();
154-
getContext().clearAtexitHooks();
153+
try {
154+
getContext().runAtexitHooks();
155+
} finally {
156+
getContext().clearAtexitHooks();
157+
}
155158
return PNone.NONE;
156159
}
157160
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
import java.util.concurrent.locks.ReentrantLock;
5151
import java.util.logging.Level;
5252

53+
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
54+
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
5355
import org.graalvm.collections.EconomicMap;
5456
import org.graalvm.collections.MapCursor;
5557
import org.graalvm.nativeimage.ImageInfo;
@@ -742,6 +744,7 @@ public int getAtexitHookCount() {
742744

743745
@TruffleBoundary
744746
public void runAtexitHooks() {
747+
// run atExitHooks in reverse order they were registered
745748
MapCursor<Object, AtExitHook> cursor = atExitHooks.getEntries();
746749
AtExitHook[] hooks = new AtExitHook[atExitHooks.size()];
747750
Object[] callables = new Object[atExitHooks.size()];
@@ -750,16 +753,31 @@ public void runAtexitHooks() {
750753
callables[i] = cursor.getKey();
751754
hooks[i] = cursor.getValue();
752755
}
756+
PException lastException = null;
753757
for (int i = hooks.length - 1; i >= 0; i--) {
754-
hooks[i].ct.call(callables[i], hooks[i].arguments, hooks[i].keywords);
758+
try {
759+
hooks[i].ct.call(callables[i], hooks[i].arguments, hooks[i].keywords);
760+
} catch (PException e) {
761+
lastException = e;
762+
if (!IsBuiltinClassProfile.profileClassSlowPath(e.getEscapedException(), PythonBuiltinClassType.SystemExit)) {
763+
System.err.println("Error in atexit._run_exitfuncs:");
764+
ExceptionUtils.printPythonLikeStackTrace(e);
765+
}
766+
}
767+
}
768+
if (lastException != null) {
769+
throw lastException;
755770
}
756771
}
757772

758773
@TruffleBoundary
759774
public void runShutdownHooks() {
760775
handler.shutdown();
761-
// run atExitHooks in reverse order they were registered
762-
runAtexitHooks();
776+
try {
777+
runAtexitHooks();
778+
} catch (PException e) {
779+
// It was printed already, so just discard
780+
}
763781
for (ShutdownHook h : shutdownHooks) {
764782
h.call(this);
765783
}

0 commit comments

Comments
 (0)