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 handler
  • internal/service/worker/worker.go, Worker.Stop cancels before it drains
  • internal/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.

Send me an issue

Written from the public pull request and issue. Your diagnosis stays private unless you say otherwise.

Next step

Send me your project, or the part your team can’t get to.

Send me your project

My last client result, a reports page cut from 3,800 requests per load to 3. The brief and the repo are enough to start.

How it starts

  1. [1]Send your project
  2. [2]Get a free plan
  3. [3]Approve the first milestone