Dagu workers stop gracefully on SIGINT and SIGTERM
dagucloud/dagu, Go, 4.5k stars. The free diagnosis covers the cause, the files and the plan, written for your issue within one working day. The tests come in the sprint.
The issue, in one line
The dagu worker process ignored SIGINT and SIGTERM, so a deploy or a restart killed running DAG runs with no handlers and no final status. The issue.
The cause
The worker installed no signal handler. A SIGTERM from systemd or Docker ended the process with exit 143, and Worker.Stop never ran. A signal-aware context alone isn’t enough, because run contexts derive from the worker context. Cancelling it would cancel the steps and their handlers too.
Where it lives
internal/cmd/worker.go, runWorker starts the worker with no signal handlerinternal/service/worker/worker.go, Worker.Stop cancels before it drainsinternal/service/worker/remote_handler.go, where each task registers how it can be signalled
The fix, planned in the free diagnosis
- Install the same shutdown handler the coordinator already uses, so a signal runs Worker.Stop.
- In Stop, stop the pollers first so no new task is claimed, then send SIGTERM to each running task so its cleanup and lifecycle handlers run.
- Cancel the internal context only after the running tasks finish, and stop deriving task contexts from the poll context.
How it’s proven, in the sprint
- A new test, TestWorkerSignalShutdown, fails on main and passes on the branch five times out of five.
- A new test, TestCancellation_WorkerStopDrainsRun, traps TERM in a step and checks that both the step and its exit handler finish.
- The full distributed suite passes on both, 123 tests on main and 124 on the branch, where the extra one is the new drain test.
What wasn’t tested, said up front
The full make test, the race detector on the distributed suite, Linux and Windows runtime tests, and the UI.
What happened next, after the sprint
It was merged on 2026-10-07 about 10 hours after it opened, with 221 lines added and 11 removed. The reviewer wrote “The drain design is the right one, and the writeup made it easy to verify” (source). Open the pull request.
Written from the public pull request and issue. Your diagnosis stays private unless you say otherwise.