Skip to content

optional signal_shutdown argument to Worker.run#1629

Open
DawidBudzynsky wants to merge 1 commit into
temporalio:mainfrom
DawidBudzynsky:signal-shutdown
Open

optional signal_shutdown argument to Worker.run#1629
DawidBudzynsky wants to merge 1 commit into
temporalio:mainfrom
DawidBudzynsky:signal-shutdown

Conversation

@DawidBudzynsky

Copy link
Copy Markdown

What was changed

Added an optional, keyword-only signal_shutdown argument to Worker.run:

await worker.run(signal_shutdown=[signal.SIGTERM, signal.SIGINT])

When set, the listed OS signals initiate the same graceful shutdown as calling Worker.shutdown(). Handlers are installed for the duration of the run() call and removed on exit (including when run() exits via a fatal worker error).

Implementation notes:

  • Uses loop.add_signal_handler where available; the handler sets the existing internal _shutdown_event, i.e. the exact same trigger shutdown() uses.
  • Falls back to signal.signal on platforms where add_signal_handler is unsupported (e.g. Windows), scheduling the shutdown via loop.call_soon_threadsafe so a blocked event loop is still woken.
  • Previous handlers are restored on exit; restoration tolerates a None previous handler (which signal.signal would otherwise reject).
  • Default behavior is unchanged: with no signal_shutdown argument (or an empty sequence), no handlers are installed.

Why?

Workers commonly run in containers/orchestrators (Kubernetes, systemd, etc.) that signal SIGTERM/SIGINT to request shutdown. Previously, translating those signals into a graceful Worker.shutdown() was left entirely to the caller's own boilerplate. This makes the common case a one-line opt-in while keeping the explicit shutdown() path fully working and the default behavior untouched.

Checklist

  1. How was this tested:
    Added 7 tests in tests/worker/test_worker.py (all passing locally against a
    dev server):
  • default (no arg) behavior is unchanged
  • empty sequence is a no-op and leaves existing handlers untouched
  • a configured signal triggers graceful shutdown and run() returns cleanly
  • any one of multiple registered signals triggers shutdown
  • handlers are removed after run() returns
  • explicit shutdown() still works when signal_shutdown is registered
  • handlers are removed even when run() exits via a fatal worker error
  1. Any docs updates needed?
    The new argument is documented in the Worker.run docstring, and a entry was added to CHANGELOG.md. No
    docs.temporal.io changes required.

@DawidBudzynsky DawidBudzynsky requested a review from a team as a code owner June 30, 2026 09:37
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Dawid Budzyński seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants