Skip to content

Commit fbf5dff

Browse files
committed
Retry GIL acquisition on exception
1 parent 6343147 commit fbf5dff

File tree

5 files changed

+38
-18
lines changed

5 files changed

+38
-18
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ public static PException checkThrowableBeforeNative(Throwable t, String where1,
290290
if (t instanceof StackOverflowError soe) {
291291
CompilerDirectives.transferToInterpreter();
292292
PythonContext context = PythonContext.get(null);
293-
context.reacquireGilAfterStackOverflow();
293+
context.ensureGilAfterFailure();
294294
PBaseException newException = context.factory().createBaseException(RecursionError, ErrorMessages.MAXIMUM_RECURSION_DEPTH_EXCEEDED, EMPTY_OBJECT_ARRAY);
295295
throw ExceptionUtils.wrapJavaException(soe, null, newException);
296296
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/hpy/GraalHPyNativeContext.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -221,7 +221,7 @@ public static PException checkThrowableBeforeNative(Throwable t, String where1,
221221
if (t instanceof StackOverflowError soe) {
222222
CompilerDirectives.transferToInterpreter();
223223
PythonContext context = PythonContext.get(null);
224-
context.reacquireGilAfterStackOverflow();
224+
context.ensureGilAfterFailure();
225225
PBaseException newException = context.factory().createBaseException(RecursionError, ErrorMessages.MAXIMUM_RECURSION_DEPTH_EXCEEDED, EMPTY_OBJECT_ARRAY);
226226
throw ExceptionUtils.wrapJavaException(soe, null, newException);
227227
}

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

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -88,7 +88,18 @@ public void release(PythonContext context, boolean wasAcquired) {
8888
@Override
8989
public boolean acquire(PythonContext context, Node location) {
9090
if (binaryProfile.profile(!context.ownsGil())) {
91-
TruffleSafepoint.setBlockedThreadInterruptible(location, PythonContext::acquireGil, context);
91+
try {
92+
TruffleSafepoint.setBlockedThreadInterruptible(location, PythonContext::acquireGil, context);
93+
} catch (Throwable t) {
94+
/*
95+
* Safepoint actions may throw exceptions, so we need to make sure that we
96+
* really acquire the GIL in the end before we hand the exception to python. And
97+
* let's not allow safepoint actions anymore so the exception doesn't get
98+
* swallowed.
99+
*/
100+
context.ensureGilAfterFailure();
101+
throw t;
102+
}
92103
return true;
93104
}
94105
return false;
@@ -128,7 +139,18 @@ public final void release(boolean wasAcquired) {
128139
public final boolean acquire(PythonContext context, Node location) {
129140
if (!context.ownsGil()) {
130141
if (!context.tryAcquireGil()) {
131-
TruffleSafepoint.setBlockedThreadInterruptible(location, PythonContext::acquireGil, context);
142+
try {
143+
TruffleSafepoint.setBlockedThreadInterruptible(location, PythonContext::acquireGil, context);
144+
} catch (Throwable t) {
145+
/*
146+
* Safepoint actions may throw exceptions, so we need to make sure that we
147+
* really acquire the GIL in the end before we hand the exception to python.
148+
* And let's not allow safepoint actions anymore so the exception doesn't
149+
* get swallowed.
150+
*/
151+
context.ensureGilAfterFailure();
152+
throw t;
153+
}
132154
}
133155
return true;
134156
}

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2234,18 +2234,16 @@ public CyclicAssumption getNativeClassStableAssumption(PythonNativeClass cls, bo
22342234
}
22352235

22362236
/**
2237-
* This method is intended to be called to re-acquire the GIL after a {@link StackOverflowError}
2238-
* was catched. To reduce the probability that re-acquiring the GIL causes again a
2239-
* {@link StackOverflowError}, it is important to keep this method as simple as possible. In
2240-
* particular, do not add calls if there is a way to avoid it.
2237+
* Acquire GIL after the normal GIL acquisition failed or there is a possibility that finally
2238+
* blocks were skipped, such as after a {@link StackOverflowError}. To reduce the probability
2239+
* that re-acquiring the GIL causes again a {@link StackOverflowError}, it is important to keep
2240+
* this method as simple as possible. In particular, do not add calls if there is a way to avoid
2241+
* it.
22412242
*/
2242-
public void reacquireGilAfterStackOverflow() {
2243-
while (!ownsGil()) {
2244-
try {
2245-
acquireGil();
2246-
} catch (InterruptedException ignored) {
2247-
// just keep trying
2248-
}
2243+
@TruffleBoundary
2244+
public void ensureGilAfterFailure() {
2245+
if (!ownsGil()) {
2246+
globalInterpreterLock.lock();
22492247
}
22502248
}
22512249

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/exception/ExceptionUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ public static PException wrapJavaException(Throwable e, Node node, PBaseExceptio
273273
public static PException wrapJavaExceptionIfApplicable(Node location, Throwable e, PythonObjectFactory factory) {
274274
if (e instanceof StackOverflowError) {
275275
CompilerDirectives.transferToInterpreterAndInvalidate();
276-
PythonContext.get(null).reacquireGilAfterStackOverflow();
276+
PythonContext.get(null).ensureGilAfterFailure();
277277
return ExceptionUtils.wrapJavaException(e, location, factory.createBaseException(RecursionError, ErrorMessages.MAXIMUM_RECURSION_DEPTH_EXCEEDED, new Object[]{}));
278278
}
279279
if (e instanceof OutOfMemoryError) {

0 commit comments

Comments
 (0)