Skip to content

Commit ce10680

Browse files
committed
[GR-29773] Workaround to enter() when creating the Fiber and not during finalizeContext
* Truffle seems to not support enter() in finalizeContext() currently.
1 parent a76ef4d commit ce10680

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

src/main/java/org/truffleruby/core/fiber/FiberManager.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,15 @@ public RubyFiber createFiber(RubyLanguage language, RubyContext context, RubyThr
102102
}
103103

104104
public void initialize(RubyFiber fiber, RubyProc block, Node currentNode) {
105+
final TruffleContext truffleContext = context.getEnv().getContext();
106+
105107
ThreadManager.FIBER_BEING_SPAWNED.set(fiber);
106108
try {
107-
context.getThreadManager().spawnFiber(fiber, () -> fiberMain(context, fiber, block, currentNode));
108-
waitForInitialization(context, fiber, currentNode);
109+
context.getThreadManager().leaveAndEnter(truffleContext, currentNode, () -> {
110+
context.getThreadManager().spawnFiber(fiber, () -> fiberMain(context, fiber, block, currentNode));
111+
waitForInitialization(context, fiber, currentNode);
112+
return BlockingAction.SUCCESS;
113+
}, context.getThreadManager().isRubyManagedThread(Thread.currentThread()));
109114
} finally {
110115
ThreadManager.FIBER_BEING_SPAWNED.remove();
111116
}
@@ -115,10 +120,16 @@ public void initialize(RubyFiber fiber, RubyProc block, Node currentNode) {
115120
public static void waitForInitialization(RubyContext context, RubyFiber fiber, Node currentNode) {
116121
final CountDownLatch initializedLatch = fiber.initializedLatch;
117122

118-
context.getThreadManager().runUntilResultKeepStatus(currentNode, () -> {
123+
final BlockingAction<Boolean> blockingAction = () -> {
119124
initializedLatch.await();
120125
return BlockingAction.SUCCESS;
121-
});
126+
};
127+
128+
if (context.getEnv().getContext().isEntered()) {
129+
context.getThreadManager().runUntilResultKeepStatus(currentNode, blockingAction);
130+
} else {
131+
ThreadManager.retryWhileInterrupted(blockingAction);
132+
}
122133

123134
final Throwable uncaughtException = fiber.uncaughtException;
124135
if (uncaughtException != null) {
@@ -141,9 +152,14 @@ private void fiberMain(RubyContext context, RubyFiber fiber, RubyProc block, Nod
141152
final TruffleContext truffleContext = context.getEnv().getContext();
142153
assert !truffleContext.isEntered();
143154

144-
final FiberMessage message = waitMessage(fiber);
145-
final Object prev = truffleContext.enter(currentNode);
155+
final Object prev = truffleContext.enter(currentNode); // enter and leave now to workaround GR-29773
146156
context.getSafepointManager().enterThread(); // not done in start() above because the context was not entered
157+
final FiberMessage message = context.getThreadManager().leaveAndEnter(truffleContext, currentNode, () -> {
158+
// fully initialized
159+
fiber.initializedLatch.countDown();
160+
return waitMessage(fiber);
161+
}, true);
162+
147163
try {
148164
final Object result;
149165
try {
@@ -277,9 +293,6 @@ public void start(RubyFiber fiber, Thread javaThread, boolean entered) {
277293
if (threadManager.isRubyManagedThread(javaThread) && Thread.currentThread() == javaThread && entered) {
278294
context.getSafepointManager().enterThread();
279295
}
280-
281-
// fully initialized
282-
fiber.initializedLatch.countDown();
283296
}
284297

285298
public void cleanup(RubyFiber fiber, Thread javaThread, boolean entered) {

src/main/java/org/truffleruby/core/thread/ThreadManager.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ public void initialize(RubyThread rubyThread, Node currentNode, String info, Str
287287
thread.setName(NAME_PREFIX + " id=" + thread.getId() + " from " + info);
288288

289289
thread.start();
290+
291+
// Must not leave the context here, to perform safepoint actions, if e.g. the new thread Thread#raise this one
290292
FiberManager.waitForInitialization(context, rootFiber, currentNode);
291293
}
292294

@@ -396,7 +398,10 @@ private void start(RubyThread thread, Thread javaThread) {
396398
registerThread(thread);
397399

398400
final FiberManager fiberManager = thread.fiberManager;
399-
fiberManager.start(fiberManager.getRootFiber(), javaThread, true);
401+
final RubyFiber rootFiber = fiberManager.getRootFiber();
402+
fiberManager.start(rootFiber, javaThread, true);
403+
// fully initialized
404+
rootFiber.initializedLatch.countDown();
400405
}
401406

402407
public void cleanup(RubyThread thread, Thread javaThread) {

0 commit comments

Comments
 (0)