Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,14 @@ public final class VirtualThreadInstrumentation extends InstrumenterModule.Conte
Instrumenter.HasMethodAdvice,
ExcludeFilterProvider {

// Preload classes used by Context.swap() to avoid class loading on the virtual thread mount path.
// DatadogClassLoader loads these from a JarFile using synchronized I/O, which pins
// virtual thread carrier threads and can deadlock the application.
/**
* Preloads mount/unmount helpers to avoid class loading during a JVMTI mount transition. Class
* loading can wait for that same transition to finish, or pin carriers in synchronized jar I/O.
*/
private static final String[] PRELOAD_CLASS_NAMES = {
"datadog.trace.core.scopemanager.ScopeContext", "datadog.trace.core.scopemanager.ScopeStack"
VIRTUAL_THREAD_STATE_CLASS_NAME,
"datadog.trace.core.scopemanager.ScopeContext",
"datadog.trace.core.scopemanager.ScopeStack"
};

public VirtualThreadInstrumentation() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package datadog.smoketest.concurrent;

public class VirtualThreadStartup {
public static void main(String[] args) throws InterruptedException {
boolean[] ran = {false};
Thread thread = Thread.startVirtualThread(() -> ran[0] = true);
thread.join();
if (!ran[0]) {
throw new AssertionError("Virtual thread did not execute");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package datadog.smoketest.concurrent;

import static datadog.smoketest.backend.AgentBackend.testAgent;
import static java.util.concurrent.TimeUnit.SECONDS;

import datadog.smoketest.SmokeCliApp;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

class VirtualThreadStartupSmokeTest {
@RegisterExtension
static final SmokeCliApp app =
SmokeCliApp.named("virtual-thread-startup")
.mainClass(
"datadog.smoketest.concurrent.VirtualThreadStartup",
System.getProperty("datadog.smoketest.shadowJar.path"))
.jvmArgs(
"-Djdk.virtualThreadScheduler.parallelism=1",
"-Djdk.virtualThreadScheduler.maxPoolSize=1")
.backend(testAgent())
.skipTelemetryCheck()
.build();

@Test
void startsVirtualThreadWithoutActiveContext() {
app.assertCompletesWithValue(30, SECONDS, 0);
}
}
Loading