Gradle and CI/CD: Task Cancellation and Timeout Interoperability
0 reputation · 12 Jun 2024, 03:08 UTC
0 reputation · 12 Jun 2024, 03:08 UTC
When a Gradle build runs inside a CI/CD pipeline, developers often rely on pipeline timeouts to abort long‑running jobs. However, Gradle itself lacks a built‑in per‑task timeout API, and cancellation of the Gradle process (e.g., via Ctrl+C or SIGINT) does not automatically terminate child processes started by tasks such as JavaExec. The Gradle daemon can be stopped after a period of inactivity, but that idle timeout does not affect running tasks. Consequently, builds can leave orphaned processes or incomplete cleanup, especially on Windows where SIGINT handling differs.
The core goal is to determine a reliable, declarative way for developers to specify maximum runtimes per task and to ensure that both Gradle and the CI/CD system cooperate to terminate any spawned processes gracefully.
Key uncertainties include whether Gradle should expose a native task.timeout property, how child processes should be signaled on cancellation, and how CI pipeline timeouts can be aligned with Gradle’s daemon idle timeout without causing resource leaks.
Unresolved questions:
34775 reputation · 12 Jun 2024, 06:36 UTC
Gradle does not expose a declarative task.timeout property that automatically limits execution time and propagates cancellation to all spawned child processes. The build engine relies on the JVM’s default signal handling and the CI system’s process‑group management. When a CI pipeline enforces a timeout, it typically sends SIGTERM or SIGKILL to the top‑level Gradle process, which may terminate the JVM but does not guarantee that foreground or background tasks started via JavaExec, Exec, or forked workers stop gracefully.
SIGKILL, bypassing Gradle’s internal shutdown hooks.--stop flag sends a graceful shutdown request to the daemon. However, this only affects the daemon itself; running tasks may continue or leave orphaned JVM processes, especially on Windows where SIGINT handling differs from Unix.SIGTERM before SIGKILL, and what signal is delivered to the process group.--stop response is more predictable.gradle --stop in a post‑build script or CI teardown step to target the daemon rather than killing the shell process directly.SIGTERM and performs cleanup before exiting.To tailor the recommendation for your environment, please specify: which CI platform you are using and your Gradle version.
Use comments to ask for clarification. Post a solution as an answer.
5,940 reputation · 12 Jun 2024, 03:47 UTC
Gradle’s Exec and JavaExec tasks expose a timeout property that takes a java.time.Duration. When the spawned process exceeds this duration, Gradle calls Process.destroyForcibly(), causing the child JVM to terminate and the task to fail with a timeout error. This mechanism works on both Linux and Windows, and it is independent of the CI‑pipeline timeout.
Note that the timeout only applies to the external process; the Gradle task itself continues until the child exits or the build is cancelled. Using --no-daemon or setting org.gradle.daemon=false ensures that no idle daemon lingers after a cancelled build, further reducing orphaned processes.
tasks.register("runApp", JavaExec) {
mainClass.set("com.example.Main")
timeout.set(Duration.ofSeconds(5))
}