From 7993bf5aa98a6a7fdf77c2f2900ce4296e28259b Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Thu, 5 Feb 2026 19:59:09 -0500 Subject: [PATCH 1/2] Fixed issue with recursive calls which can cause StackOverflowError. Reverted usage of `slf4j-simple` back to `logback`, as real root-cause of hanged tests on CI was flooding error to logs. --- .../WrapRunnableAsNewTaskInstrumentation.java | 12 ++++++++- .../java-concurrent-21.0/build.gradle | 2 -- .../java-lang/java-lang-21.0/build.gradle | 2 -- .../vertx-web/vertx-web-3.4/build.gradle | 2 -- gradle/slf4j-simple.gradle | 27 ------------------- 5 files changed, 11 insertions(+), 34 deletions(-) delete mode 100644 gradle/slf4j-simple.gradle diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/main/java/datadog/trace/instrumentation/java/concurrent/WrapRunnableAsNewTaskInstrumentation.java b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/main/java/datadog/trace/instrumentation/java/concurrent/WrapRunnableAsNewTaskInstrumentation.java index f4690009d1d..41303a9f006 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/main/java/datadog/trace/instrumentation/java/concurrent/WrapRunnableAsNewTaskInstrumentation.java +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-1.8/src/main/java/datadog/trace/instrumentation/java/concurrent/WrapRunnableAsNewTaskInstrumentation.java @@ -13,6 +13,7 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.InstrumenterModule; +import datadog.trace.bootstrap.CallDepthThreadLocalMap; import datadog.trace.bootstrap.instrumentation.java.concurrent.NewTaskForPlaceholder; import datadog.trace.bootstrap.instrumentation.java.concurrent.Wrapper; import java.util.concurrent.AbstractExecutorService; @@ -97,7 +98,16 @@ public static void cancel( @Advice.Thrown Throwable error) { // don't cancel unless we did the wrapping if (wrapped && null != error && task instanceof RunnableFuture) { - ((RunnableFuture) task).cancel(true); + // Guard against recursive cancel calls which can cause StackOverflowError + // when executor.execute() fails during shutdown and triggers promise notifications + int callDepth = CallDepthThreadLocalMap.incrementCallDepth(RunnableFuture.class); + try { + if (callDepth == 0) { + ((RunnableFuture) task).cancel(true); + } + } finally { + CallDepthThreadLocalMap.decrementCallDepth(RunnableFuture.class); + } } } } diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-21.0/build.gradle b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-21.0/build.gradle index 7a42cad69ed..3a740998d52 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-21.0/build.gradle +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-21.0/build.gradle @@ -1,6 +1,4 @@ apply from: "$rootDir/gradle/java.gradle" -// Use slf4j-simple as default; logback has a high chance of getting stuck in a deadlock on CI. -apply from: "$rootDir/gradle/slf4j-simple.gradle" apply plugin: 'idea' testJvmConstraints { diff --git a/dd-java-agent/instrumentation/java/java-lang/java-lang-21.0/build.gradle b/dd-java-agent/instrumentation/java/java-lang/java-lang-21.0/build.gradle index 97c18d0e083..ea64dd32418 100644 --- a/dd-java-agent/instrumentation/java/java-lang/java-lang-21.0/build.gradle +++ b/dd-java-agent/instrumentation/java/java-lang/java-lang-21.0/build.gradle @@ -3,8 +3,6 @@ plugins { } apply from: "$rootDir/gradle/java.gradle" -// Use slf4j-simple as default; logback has a high chance of getting stuck in a deadlock on CI. -apply from: "$rootDir/gradle/slf4j-simple.gradle" testJvmConstraints { minJavaVersion = JavaVersion.VERSION_21 diff --git a/dd-java-agent/instrumentation/vertx/vertx-web/vertx-web-3.4/build.gradle b/dd-java-agent/instrumentation/vertx/vertx-web/vertx-web-3.4/build.gradle index 823193ea978..56311523214 100644 --- a/dd-java-agent/instrumentation/vertx/vertx-web/vertx-web-3.4/build.gradle +++ b/dd-java-agent/instrumentation/vertx/vertx-web/vertx-web-3.4/build.gradle @@ -1,6 +1,4 @@ apply from: "$rootDir/gradle/java.gradle" -// Use slf4j-simple as default; logback has a high chance of getting stuck in a deadlock on CI. -apply from: "$rootDir/gradle/slf4j-simple.gradle" testJvmConstraints { // TODO Java 17: This version of vertx-web doesn't support Java 17 diff --git a/gradle/slf4j-simple.gradle b/gradle/slf4j-simple.gradle deleted file mode 100644 index a83ef57a71a..00000000000 --- a/gradle/slf4j-simple.gradle +++ /dev/null @@ -1,27 +0,0 @@ -// Apply this script when `slf4j-simple` should be used instead of `logback`. - -configurations.configureEach { cfg -> - def name = cfg.name - - if (name.containsIgnoreCase("test")) { - // Exclude Logback from all test-like runtimeClasspath configurations. - if (name.endsWithIgnoreCase("runtimeClasspath")) { - cfg.exclude group: "ch.qos.logback" - } - - // Add slf4j-simple to all test-like runtimeOnly configurations. - if (name.endsWithIgnoreCase("runtimeOnly")) { - project.dependencies.add(name, "org.slf4j:slf4j-simple:${libs.versions.slf4j.get()}") - } - } -} - -// Configure `slf4j-simple` logger. -tasks.withType(Test).configureEach { - jvmArgs += [ - "-Dorg.slf4j.simpleLogger.defaultLogLevel=debug", - "-Dorg.slf4j.simpleLogger.showThreadName=true", - "-Dorg.slf4j.simpleLogger.showDateTime=true", - "-Dorg.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss.SSS" - ] -} From fff331eb6888cc79454c331526dce1b26a248be9 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 6 Feb 2026 09:47:30 -0500 Subject: [PATCH 2/2] Reverted deletion of slf4j-simple workaround, as it will be fixed as separate PR. --- .../java-concurrent-21.0/build.gradle | 2 ++ .../java-lang/java-lang-21.0/build.gradle | 2 ++ gradle/slf4j-simple.gradle | 27 +++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 gradle/slf4j-simple.gradle diff --git a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-21.0/build.gradle b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-21.0/build.gradle index 3a740998d52..7a42cad69ed 100644 --- a/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-21.0/build.gradle +++ b/dd-java-agent/instrumentation/java/java-concurrent/java-concurrent-21.0/build.gradle @@ -1,4 +1,6 @@ apply from: "$rootDir/gradle/java.gradle" +// Use slf4j-simple as default; logback has a high chance of getting stuck in a deadlock on CI. +apply from: "$rootDir/gradle/slf4j-simple.gradle" apply plugin: 'idea' testJvmConstraints { diff --git a/dd-java-agent/instrumentation/java/java-lang/java-lang-21.0/build.gradle b/dd-java-agent/instrumentation/java/java-lang/java-lang-21.0/build.gradle index ea64dd32418..97c18d0e083 100644 --- a/dd-java-agent/instrumentation/java/java-lang/java-lang-21.0/build.gradle +++ b/dd-java-agent/instrumentation/java/java-lang/java-lang-21.0/build.gradle @@ -3,6 +3,8 @@ plugins { } apply from: "$rootDir/gradle/java.gradle" +// Use slf4j-simple as default; logback has a high chance of getting stuck in a deadlock on CI. +apply from: "$rootDir/gradle/slf4j-simple.gradle" testJvmConstraints { minJavaVersion = JavaVersion.VERSION_21 diff --git a/gradle/slf4j-simple.gradle b/gradle/slf4j-simple.gradle new file mode 100644 index 00000000000..a83ef57a71a --- /dev/null +++ b/gradle/slf4j-simple.gradle @@ -0,0 +1,27 @@ +// Apply this script when `slf4j-simple` should be used instead of `logback`. + +configurations.configureEach { cfg -> + def name = cfg.name + + if (name.containsIgnoreCase("test")) { + // Exclude Logback from all test-like runtimeClasspath configurations. + if (name.endsWithIgnoreCase("runtimeClasspath")) { + cfg.exclude group: "ch.qos.logback" + } + + // Add slf4j-simple to all test-like runtimeOnly configurations. + if (name.endsWithIgnoreCase("runtimeOnly")) { + project.dependencies.add(name, "org.slf4j:slf4j-simple:${libs.versions.slf4j.get()}") + } + } +} + +// Configure `slf4j-simple` logger. +tasks.withType(Test).configureEach { + jvmArgs += [ + "-Dorg.slf4j.simpleLogger.defaultLogLevel=debug", + "-Dorg.slf4j.simpleLogger.showThreadName=true", + "-Dorg.slf4j.simpleLogger.showDateTime=true", + "-Dorg.slf4j.simpleLogger.dateTimeFormat=HH:mm:ss.SSS" + ] +}