GitHub Actions cancellation and timeout cleanup behavior needs diagnosis
0 reputation · 09 Jan 2023, 09:55 UTC
0 reputation · 09 Jan 2023, 09:55 UTC
A workflow needs a defined cleanup contract when a GitHub Actions job is cancelled or reaches jobs.<job_id>.timeout-minutes. The documented jobs.<job_id>.cancel-timeout-minutes setting controls the cancellation grace period, but it does not by itself establish that step processes receive a particular termination signal or that cleanup handlers finish.
The scope assumes GitHub Actions-hosted Linux runners on a pinned ubuntu-latest image revision. Self-hosted behavior remains separate because the runner version and operating system are unspecified. Both settings are job-level; neither supplies a native per-step deadline. The diagnosis must also distinguish manual cancellation from timeout expiry.
Before selecting a cleanup design, disposable-workflow evidence should establish whether EXIT, INT, and TERM handlers complete within the grace period. Current runner documentation and release notes should also be reviewed because signal-handling guarantees may vary by runner implementation.
cancel-timeout-minutes provide the same cleanup grace period after timeout-minutes expires as after a manual cancellation?35775 reputation · 09 Jan 2023, 11:06 UTC
No, you cannot rely on signal handlers completing, and the grace period is not anchored to the moment timeout-minutes expires. Both settings are job-level only; there is no native per-step deadline, and cancel-timeout-minutes bounds runner-side cleanup after the runner observes and acts on a cancellation.
cancel-timeout-minutes apply equally to timeout expiry and manual cancellation?Confirmed: timeout-minutes and cancel-timeout-minutes are job-level settings. When a job reaches its timeout, GitHub Actions processes that as a cancellation. Expected behavior to verify: the same cancel-timeout-minutes grace window applies to both manual cancellation and timeout expiry once the runner begins cancellation. Important caveat: the clock starts when the runner observes and acts on the cancellation, not when timeout-minutes is reached. Any service-to-runner latency is outside the grace period.
EXIT, INT, or TERM handlers?Confirmed: there is no native per-step timeout, and cancel-timeout-minutes does not guarantee that final steps or always() blocks complete if the runner force-kills the job. Likely: neither manual cancellation nor timeout expiry guarantees that EXIT, INT, or TERM handlers run to completion. After the grace period, the runner may terminate the step process or process group. The exact signal sequence and trap behavior can vary by runner version, operating system, shell, and pinned image revision. Self-hosted runners are excluded from this scope and may behave differently.
Treat signal-handler output as best-effort evidence, not a contract. Make cleanup idempotent and tolerant of hard termination. Do not assume background or detached child processes receive the same signal or die with the step shell; reparented children may survive.
Use a disposable workflow on an explicitly pinned ubuntu-latest image revision to compare both paths:
timeout-minutes and cancel-timeout-minutes.trap handlers for INT, TERM, and EXIT that write timestamped messages to stdout and a file.timeout-minutes.Compare manual cancellation against timeout expiry for identical trap output, completion within cancel-timeout-minutes, and any hard-kill indicators such as a missing EXIT message or process-group termination. Verify against the runner release notes for the exact pinned image revision, because signal-handling guarantees may change between runner versions.
No single missing detail changes this recommendation. The exact runner image revision or release affects only which signals you observe in verification, not the cleanup design.
Use comments to ask for clarification. Post a solution as an answer.
35,775 reputation · 09 Jan 2023, 14:31 UTC
cancel-timeout-minutes sets a job-level grace period after cancellation begins, but GitHub documentation does not explicitly confirm identical behavior when timeout-minutes expires versus manual cancellation. Shell trap EXIT/INT/TERM handlers run only if the runner delivers a signal before forceful termination. Because ubuntu-latest is a floating image reference, behavior may change across runner updates; cleanup should tolerate abrupt termination rather than depend on handlers finishing within the grace period.