Skip to content

Commit ad139ad

Browse files
committed
[GR-60399] Fix GIL hold count assertion in PythonContext.releaseGil.
PullRequest: graalpython/3613
2 parents c05deea + e2defcc commit ad139ad

File tree

8 files changed

+31
-20
lines changed

8 files changed

+31
-20
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
import com.oracle.truffle.api.CompilerDirectives;
123123
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
124124
import com.oracle.truffle.api.RootCallTarget;
125+
import com.oracle.truffle.api.TruffleSafepoint;
125126
import com.oracle.truffle.api.dsl.Bind;
126127
import com.oracle.truffle.api.dsl.Cached;
127128
import com.oracle.truffle.api.dsl.Fallback;
@@ -216,7 +217,7 @@ public abstract static class AcquireLock extends PythonBuiltinNode {
216217
public Object run(@Cached GilNode gil) {
217218
gil.release(true);
218219
try {
219-
getContext().getImportLock().lock();
220+
TruffleSafepoint.setBlockedThreadInterruptible(this, ReentrantLock::lock, getContext().getImportLock());
220221
} finally {
221222
gil.acquire();
222223
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,6 @@ Object sleep(PythonModule self, long seconds,
511511
ModuleState moduleState = self.getModuleState(ModuleState.class);
512512
moduleState.timeSlept = nanoTime() - t + moduleState.timeSlept;
513513
}
514-
PythonContext.triggerAsyncActions(this);
515514
return PNone.NONE;
516515
}
517516

@@ -581,8 +580,8 @@ private static void doSleep(Node node, double seconds, double deadline) {
581580
try {
582581
Thread.sleep(millis, nanos);
583582
} catch (InterruptedException ignored) {
583+
// Truffle would otherwise execute the action again after interrupt
584584
Thread.currentThread().interrupt();
585-
return;
586585
}
587586
}, secs);
588587
secs = deadline - timeSeconds();

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TypeBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ static Object doc(Object self, @SuppressWarnings("unused") DescriptorDeleteMarke
303303

304304
@Builtin(name = J___MRO__, minNumOfPositionalArgs = 1, isGetter = true)
305305
@GenerateNodeFactory
306-
abstract static class MroAttrNode extends PythonBuiltinNode {
306+
abstract static class MroAttrNode extends PythonUnaryBuiltinNode {
307307
@Specialization
308308
static Object doit(Object klass,
309309
@Bind("this") Node inliningTarget,

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

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@
175175
import com.oracle.graal.python.util.PythonUtils;
176176
import com.oracle.graal.python.util.ShutdownHook;
177177
import com.oracle.graal.python.util.Supplier;
178+
import com.oracle.graal.python.util.SuppressFBWarnings;
178179
import com.oracle.truffle.api.CallTarget;
179180
import com.oracle.truffle.api.CompilerAsserts;
180181
import com.oracle.truffle.api.CompilerDirectives;
@@ -2480,9 +2481,26 @@ static final String dumpStackOnAssertionHelper(String msg) {
24802481
* @see GilNode
24812482
*/
24822483
@TruffleBoundary
2484+
// intentional catch of IllegalMonitorStateException, see inline comments
2485+
@SuppressFBWarnings("IMSE_DONT_CATCH_IMSE")
24832486
void releaseGil() {
2484-
assert globalInterpreterLock.getHoldCount() == 1 : dumpStackOnAssertionHelper("trying to release the GIL with invalid hold count " + globalInterpreterLock.getHoldCount());
2485-
globalInterpreterLock.unlock();
2487+
// We allow hold count == 0 when cancelling, because a thread may have given up the GIL,
2488+
// then a cancelling (subclass of ThreadDeath) exception is thrown inside the code running
2489+
// without GIL through thread local action and in such case, we do not try to reacquire the
2490+
// GIL and let the ThreadDeath bubble up the stack to the top level and along the way we
2491+
// may have some finally blocks that are trying to release the initially acquired GIL and
2492+
// reach this method
2493+
assert globalInterpreterLock.getHoldCount() == 1 || (env.getContext().isCancelling() && globalInterpreterLock.getHoldCount() == 0) : dumpStackOnAssertionHelper(
2494+
"trying to release the GIL with invalid hold count " + globalInterpreterLock.getHoldCount());
2495+
try {
2496+
globalInterpreterLock.unlock();
2497+
} catch (IllegalMonitorStateException ex) {
2498+
// IllegalMonitorStateException is thrown if the lock is not owned by this thread, see
2499+
// the comment above why we allow it if the context is cancelling
2500+
if (!env.getContext().isCancelling()) {
2501+
throw ex;
2502+
}
2503+
}
24862504
}
24872505

24882506
/**

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

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,6 @@ public final class PythonThreadKillException extends RuntimeException {
6767
private static final long serialVersionUID = 5323687983726237118L;
6868
public static final PythonThreadKillException INSTANCE = new PythonThreadKillException();
6969

70-
/**
71-
* Creates an exception thrown to model control flow.
72-
*
73-
* @since 0.8 or earlier
74-
*/
7570
public PythonThreadKillException() {
7671
/*
7772
* We use the super constructor that initializes the cause to null. Without that, the cause
@@ -84,8 +79,6 @@ public PythonThreadKillException() {
8479

8580
/**
8681
* For performance reasons, this exception does not record any stack trace information.
87-
*
88-
* @since 0.8 or earlier
8982
*/
9083
@SuppressWarnings("sync-override")
9184
@Override

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/util/PythonSystemThreadTask.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@
5656
* {@link PythonThreadKillException}. The Java interrupt should interrupt any blocking operation,
5757
* which should then poll a safepoint. This wrapper takes care of handling
5858
* {@link PythonThreadKillException} gracefully. Note that Truffle may also shut down this thread
59-
* via TLA that throws its own internal cancellation exception, which is handled in Truffle internal
60-
* code that wraps this Runnable.
59+
* via TLA that throws its own internal cancellation exception (which inherits {@code ThreadDeath}
60+
* exception), which is handled in Truffle internal code that wraps this Runnable.
6161
*/
6262
public abstract class PythonSystemThreadTask implements Runnable {
6363
private final String name;

mx.graalpython/mx_graalpython.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,7 +1280,7 @@ def graalpython_gate_runner(args, tasks):
12801280
override_path = os.path.join(SUITE.get_mx_output_dir(), 'gradle-properties-override')
12811281
original_props_file = "graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/gradle-test-project/gradle/wrapper/gradle-wrapper.properties"
12821282
mx.copyfile(original_props_file, override_path)
1283-
mx_graalpython_gradleproject.patch_distributionUrl(override_path, original_props_file)
1283+
mx_graalpython_gradleproject.patch_distribution_url(override_path, original_props_file)
12841284
env['GRADLE_PROPERTIES_OVERRIDE'] = override_path
12851285

12861286
env["org.graalvm.maven.downloader.version"] = version
@@ -1315,7 +1315,7 @@ def graalpython_gate_runner(args, tasks):
13151315
override_path = os.path.join(SUITE.get_mx_output_dir(), 'maven-properties-override')
13161316
original_props_file = "graalpython/com.oracle.graal.python.test/src/tests/standalone/mvnw/.mvn/wrapper/maven-wrapper.properties"
13171317
mx.copyfile(original_props_file, override_path)
1318-
mx_graalpython_gradleproject.patch_distributionUrl(override_path, original_props_file, escape_colon=False)
1318+
mx_graalpython_gradleproject.patch_distribution_url(override_path, original_props_file, escape_colon=False)
13191319
env['MAVEN_PROPERTIES_OVERRIDE'] = override_path
13201320

13211321
env["org.graalvm.maven.downloader.version"] = version

mx.graalpython/mx_graalpython_gradleproject.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def gradle_wrapper_properties(project_root):
5252
return os.path.join(project_root, "gradle", "wrapper", "gradle-wrapper.properties")
5353

5454

55-
def patch_distributionUrl(properties_file, original_file=None, escape_colon=True):
55+
def patch_distribution_url(properties_file, original_file=None, escape_colon=True):
5656
def escape(s):
5757
return s.replace(':', '\\:') if escape_colon else s
5858

@@ -301,8 +301,8 @@ def _create_build_script(self, version: str | None = None):
301301
"""
302302
# Gradle wrapper
303303
shutil.copytree(os.path.join(self.subject.gradle_directory, "wrapper"), self.subject.get_output_root(), dirs_exist_ok=True)
304-
patch_distributionUrl(gradle_wrapper_properties(self.subject.get_output_root()),
305-
original_file=gradle_wrapper_properties(os.path.join(self.subject.gradle_directory, "wrapper")))
304+
patch_distribution_url(gradle_wrapper_properties(self.subject.get_output_root()),
305+
original_file=gradle_wrapper_properties(os.path.join(self.subject.gradle_directory, "wrapper")))
306306

307307
# build.gradle
308308
deps_decls = []

0 commit comments

Comments
 (0)