Skip to content

Commit bc6f210

Browse files
committed
[GR-29375] Fix disposeThread() ran from a foreign thread and add test
1 parent 385b6c7 commit bc6f210

File tree

3 files changed

+48
-1
lines changed

3 files changed

+48
-1
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ public void killOtherFibers() {
331331
context.getThreadManager().leaveAndEnter(truffleContext, null, () -> {
332332
doKillOtherFibers();
333333
return BlockingAction.SUCCESS;
334-
}, true);
334+
}, context.getThreadManager().isRubyManagedThread(Thread.currentThread()));
335335
}
336336

337337
private void doKillOtherFibers() {

src/main/java/org/truffleruby/debug/TruffleDebugNodes.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.truffleruby.core.rope.CodeRange;
5656
import org.truffleruby.core.string.RubyString;
5757
import org.truffleruby.core.string.StringNodes.MakeStringNode;
58+
import org.truffleruby.core.thread.ThreadManager;
5859
import org.truffleruby.extra.ffi.Pointer;
5960
import org.truffleruby.interop.BoxedValue;
6061
import org.truffleruby.interop.ToJavaStringNode;
@@ -1002,4 +1003,15 @@ protected RubyString parseName(InternalMethod method) {
10021003

10031004
}
10041005

1006+
/** Creates a Truffle thread that is no {@link ThreadManager#isRubyManagedThread(java.lang.Thread)}}. */
1007+
@CoreMethod(names = "create_polyglot_thread", onSingleton = true, required = 1)
1008+
public abstract static class CreatePolyglotThread extends CoreMethodArrayArgumentsNode {
1009+
@Specialization
1010+
protected Object parseName(Object hostRunnable) {
1011+
Runnable runnable = (Runnable) getContext().getEnv().asHostObject(hostRunnable);
1012+
final Thread thread = getContext().getEnv().createThread(runnable);
1013+
return getContext().getEnv().asGuestValue(thread);
1014+
}
1015+
}
1016+
10051017
}

src/test/java/org/truffleruby/MiscTest.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package org.truffleruby;
1111

1212
import static org.junit.Assert.assertEquals;
13+
import static org.junit.Assert.assertFalse;
1314
import static org.junit.Assert.assertNotEquals;
1415
import static org.junit.Assert.assertTrue;
1516

@@ -120,6 +121,40 @@ public void testIntegratorThreadRubyThreadInitialization() throws Throwable {
120121
}
121122
}
122123

124+
@Test
125+
public void testForeignThread() throws Throwable {
126+
// Tests thread initialization and finalization for a foreign thread and an embedder thread
127+
try (Context context = Context.newBuilder("ruby").allowCreateThread(true).build()) {
128+
context.eval("ruby", "$queue = Queue.new");
129+
assertEquals(context.eval("ruby", "Thread.main"), context.eval("ruby", "Thread.current"));
130+
assertTrue(context.eval("ruby", "Thread.current").toString().contains("@main"));
131+
assertFalse(context.eval("ruby", "Thread.current").toString().contains("<foreign thread>"));
132+
133+
Runnable polyglotThreadBody = () -> {
134+
context.eval("ruby", "$queue.pop");
135+
assertTrue(context.eval("ruby", "Thread.current").toString().contains("<foreign thread>"));
136+
};
137+
Thread polyglotThread = context
138+
.eval("ruby", "Truffle::Debug")
139+
.invokeMember("create_polyglot_thread", polyglotThreadBody)
140+
.asHostObject();
141+
142+
TestingThread embedderThread = new TestingThread(() -> {
143+
context.eval("ruby", "$queue.pop");
144+
assertTrue(context.eval("ruby", "Thread.current").toString().contains("<foreign thread>"));
145+
});
146+
147+
polyglotThread.start();
148+
embedderThread.start();
149+
150+
context.eval("ruby", "$queue << 1");
151+
context.eval("ruby", "$queue << 2");
152+
153+
polyglotThread.join(); // causes disposeThread(polyglotThread) to run on polyglotThread
154+
embedderThread.join();
155+
}
156+
}
157+
123158
@Ignore // TODO (eregon, 8 April 2020): not yet working
124159
@Test
125160
public void testIntegratorThreadContextClosedOnOtherThread() throws Throwable {

0 commit comments

Comments
 (0)