From 0a826c540218d3faeee0558ec919453a34f5ca99 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Thu, 5 Mar 2026 17:41:49 -0500 Subject: [PATCH 1/3] Refactor cleanupSpec() to remove infinite loop with deterministic control flow. --- .../datadog/smoketest/ProcessManager.groovy | 52 ++++++++++++------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/dd-smoke-tests/src/main/groovy/datadog/smoketest/ProcessManager.groovy b/dd-smoke-tests/src/main/groovy/datadog/smoketest/ProcessManager.groovy index 5c06793dd15..954f6e73fc5 100644 --- a/dd-smoke-tests/src/main/groovy/datadog/smoketest/ProcessManager.groovy +++ b/dd-smoke-tests/src/main/groovy/datadog/smoketest/ProcessManager.groovy @@ -3,7 +3,6 @@ package datadog.smoketest import datadog.trace.agent.test.utils.PortUtils import java.nio.file.Files import java.nio.file.Paths -import java.util.concurrent.TimeoutException import spock.lang.AutoCleanup import spock.lang.Shared import spock.lang.Specification @@ -108,32 +107,45 @@ abstract class ProcessManager extends Specification { } def cleanupSpec() { + Throwable firstFailure = null testedProcesses.each { tp -> - int maxAttempts = 10 + if (tp == null) { + return // closure continue — skip null slots + } + Integer exitValue - for (int attempt = 1; attempt <= maxAttempts != null; attempt++) { - try { - exitValue = tp?.exitValue() - break + try { + exitValue = tp.exitValue() + } catch (Throwable ignored) { + System.out.println("Destroying instrumented process") + tp.destroy() + + if (!tp.waitFor(5, TimeUnit.SECONDS)) { + System.out.println("Destroying instrumented process (forced)") + tp.destroyForcibly() + tp.waitFor(10, TimeUnit.SECONDS) } - catch (Throwable ignored) { - if (attempt == 1) { - System.out.println("Destroying instrumented process") - tp.destroy() - } - if (attempt == maxAttempts - 1) { - System.out.println("Destroying instrumented process (forced)") - tp.destroyForcibly() + + try { + exitValue = tp.exitValue() + } catch (Throwable ignoredAgain) { + // Process did not exit even after SIGKILL — record failure but continue + // cleaning up any remaining processes before propagating. + def failure = new RuntimeException("Instrumented process failed to exit after SIGKILL") + if (firstFailure == null) { + firstFailure = failure + } else { + firstFailure.addSuppressed(failure) } - sleep 1_000 + return // closure continue } } - if (exitValue != null) { - System.out.println("Instrumented process exited with " + exitValue) - } else if (tp != null) { - throw new TimeoutException("Instrumented process failed to exit") - } + System.out.println("Instrumented process exited with " + exitValue) + } + + if (firstFailure != null) { + throw firstFailure } } From 591885d82ae43d3beb0609fe3abd0feb9eb92786 Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Thu, 5 Mar 2026 18:33:48 -0500 Subject: [PATCH 2/3] Added missing import --- .../src/main/groovy/datadog/smoketest/ProcessManager.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/dd-smoke-tests/src/main/groovy/datadog/smoketest/ProcessManager.groovy b/dd-smoke-tests/src/main/groovy/datadog/smoketest/ProcessManager.groovy index 954f6e73fc5..fc503779d0d 100644 --- a/dd-smoke-tests/src/main/groovy/datadog/smoketest/ProcessManager.groovy +++ b/dd-smoke-tests/src/main/groovy/datadog/smoketest/ProcessManager.groovy @@ -3,6 +3,7 @@ package datadog.smoketest import datadog.trace.agent.test.utils.PortUtils import java.nio.file.Files import java.nio.file.Paths +import java.util.concurrent.TimeUnit import spock.lang.AutoCleanup import spock.lang.Shared import spock.lang.Specification From c7f9c446b51b2e318069511812b14b0aaca4805a Mon Sep 17 00:00:00 2001 From: Alexey Kuznetsov Date: Fri, 6 Mar 2026 14:02:52 -0500 Subject: [PATCH 3/3] Fixed review comments. --- .gitignore | 1 + .../src/main/groovy/datadog/smoketest/ProcessManager.groovy | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index c4ed1cca938..efe0ddbf28b 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,7 @@ out/ # Others # ########## +/dumps /logs/* /bin /out diff --git a/dd-smoke-tests/src/main/groovy/datadog/smoketest/ProcessManager.groovy b/dd-smoke-tests/src/main/groovy/datadog/smoketest/ProcessManager.groovy index fc503779d0d..83a8ff2ccb3 100644 --- a/dd-smoke-tests/src/main/groovy/datadog/smoketest/ProcessManager.groovy +++ b/dd-smoke-tests/src/main/groovy/datadog/smoketest/ProcessManager.groovy @@ -118,11 +118,11 @@ abstract class ProcessManager extends Specification { try { exitValue = tp.exitValue() } catch (Throwable ignored) { - System.out.println("Destroying instrumented process") + System.err.println("Destroying instrumented process") tp.destroy() if (!tp.waitFor(5, TimeUnit.SECONDS)) { - System.out.println("Destroying instrumented process (forced)") + System.err.println("Destroying instrumented process (forced)") tp.destroyForcibly() tp.waitFor(10, TimeUnit.SECONDS) } @@ -142,7 +142,7 @@ abstract class ProcessManager extends Specification { } } - System.out.println("Instrumented process exited with " + exitValue) + System.err.println("Instrumented process exited with " + exitValue) } if (firstFailure != null) {