Skip to content

Commit 2d155e5

Browse files
committed
Fix atexit execution order
1 parent 805c887 commit 2d155e5

File tree

3 files changed

+18
-25
lines changed

3 files changed

+18
-25
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_args
12
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_badargs
23
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_bound_methods
34
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_clear
45
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_exit
56
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_order
67
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_raise
8+
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_shutdown
9+
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_stress
710
*graalpython.lib-python.3.test.test_atexit.GeneralTest.test_unregister
811
*graalpython.lib-python.3.test.test_atexit.SubinterpreterTest.test_callback_on_subinterpreter_teardown
912
*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: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ Object register(Object callable, Object[] arguments, PKeyword[] keywords) {
121121
abstract static class UnregisterNode extends PythonUnaryBuiltinNode {
122122
@Specialization
123123
Object register(Object callable) {
124-
getContext().deregisterAtexitHook(callable);
124+
getContext().unregisterAtexitHook(callable);
125125
return PNone.NONE;
126126
}
127127
}
@@ -150,11 +150,7 @@ int get() {
150150
abstract static class RunExitfuncsNode extends PythonBuiltinNode {
151151
@Specialization
152152
Object run() {
153-
try {
154-
getContext().runAtexitHooks();
155-
} finally {
156-
getContext().clearAtexitHooks();
157-
}
153+
getContext().runAtexitHooks();
158154
return PNone.NONE;
159155
}
160156
}

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

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,11 @@
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;
55-
import org.graalvm.collections.EconomicMap;
56-
import org.graalvm.collections.MapCursor;
5753
import org.graalvm.nativeimage.ImageInfo;
5854
import org.graalvm.options.OptionKey;
5955

6056
import com.oracle.graal.python.PythonLanguage;
57+
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
6158
import com.oracle.graal.python.builtins.objects.PNone;
6259
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
6360
import com.oracle.graal.python.builtins.objects.cext.PythonNativeClass;
@@ -82,6 +79,7 @@
8279
import com.oracle.graal.python.nodes.SpecialMethodNames;
8380
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
8481
import com.oracle.graal.python.nodes.call.CallNode;
82+
import com.oracle.graal.python.nodes.object.IsBuiltinClassProfile;
8583
import com.oracle.graal.python.runtime.AsyncHandler.AsyncAction;
8684
import com.oracle.graal.python.runtime.exception.ExceptionUtils;
8785
import com.oracle.graal.python.runtime.exception.PException;
@@ -187,11 +185,13 @@ void reprLeave(Object item) {
187185
}
188186

189187
private static final class AtExitHook {
188+
final Object callable;
190189
final Object[] arguments;
191190
final PKeyword[] keywords;
192191
final CallTarget ct;
193192

194-
AtExitHook(Object[] arguments, PKeyword[] keywords, CallTarget ct) {
193+
AtExitHook(Object callable, Object[] arguments, PKeyword[] keywords, CallTarget ct) {
194+
this.callable = callable;
195195
this.arguments = arguments;
196196
this.keywords = keywords;
197197
this.ct = ct;
@@ -211,7 +211,7 @@ private static final class AtExitHook {
211211
private PythonModule mainModule;
212212
private final PythonCore core;
213213
private final List<ShutdownHook> shutdownHooks = new ArrayList<>();
214-
private final EconomicMap<Object, AtExitHook> atExitHooks = EconomicMap.create(0);
214+
private final List<AtExitHook> atExitHooks = new ArrayList<>();
215215
private final HashMap<PythonNativeClass, CyclicAssumption> nativeClassStableAssumptions = new HashMap<>();
216216
private final AtomicLong globalId = new AtomicLong(Integer.MAX_VALUE * 2L + 4L);
217217
private final ThreadGroup threadGroup = new ThreadGroup(GRAALPYTHON_THREADS);
@@ -717,12 +717,12 @@ public void registerAtexitHook(ShutdownHook shutdownHook) {
717717

718718
@TruffleBoundary
719719
public void registerAtexitHook(Object callable, Object[] arguments, PKeyword[] keywords, CallTarget ct) {
720-
atExitHooks.put(callable, new AtExitHook(arguments, keywords, ct));
720+
atExitHooks.add(new AtExitHook(callable, arguments, keywords, ct));
721721
}
722722

723723
@TruffleBoundary
724-
public void deregisterAtexitHook(Object callable) {
725-
atExitHooks.removeKey(callable);
724+
public void unregisterAtexitHook(Object callable) {
725+
atExitHooks.removeIf(hook -> hook.callable == callable);
726726
}
727727

728728
@TruffleBoundary
@@ -745,18 +745,11 @@ public int getAtexitHookCount() {
745745
@TruffleBoundary
746746
public void runAtexitHooks() {
747747
// run atExitHooks in reverse order they were registered
748-
MapCursor<Object, AtExitHook> cursor = atExitHooks.getEntries();
749-
AtExitHook[] hooks = new AtExitHook[atExitHooks.size()];
750-
Object[] callables = new Object[atExitHooks.size()];
751-
for (int i = 0; i < hooks.length; i++) {
752-
cursor.advance();
753-
callables[i] = cursor.getKey();
754-
hooks[i] = cursor.getValue();
755-
}
756748
PException lastException = null;
757-
for (int i = hooks.length - 1; i >= 0; i--) {
749+
for (int i = atExitHooks.size() - 1; i >= 0; i--) {
750+
AtExitHook hook = atExitHooks.get(i);
758751
try {
759-
hooks[i].ct.call(callables[i], hooks[i].arguments, hooks[i].keywords);
752+
hook.ct.call(hook.callable, hook.arguments, hook.keywords);
760753
} catch (PException e) {
761754
lastException = e;
762755
if (!IsBuiltinClassProfile.profileClassSlowPath(e.getEscapedException(), PythonBuiltinClassType.SystemExit)) {
@@ -765,6 +758,7 @@ public void runAtexitHooks() {
765758
}
766759
}
767760
}
761+
atExitHooks.clear();
768762
if (lastException != null) {
769763
throw lastException;
770764
}

0 commit comments

Comments
 (0)