Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Implement systemd notify-reload mechanism
Avoid the use of 'ExecReload' as advised in systemd.service(5)
  • Loading branch information
zigarn committed Oct 10, 2025
commit 5e772146267fc4f25d2bae24e4016290981ddb05
6 changes: 4 additions & 2 deletions docs/source/deploy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ to the newly created unix socket:

[Service]
# gunicorn can let systemd know when it is ready
Type=notify
# if systemd versions >= v253, otherwise use 'Type=notify'
Type=notify-reload
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Beware that systemd considers most unit parsing errors safe to proceed with, so this can unexpectedly revert to the default of simple on v<253, e.g. on some stable distributions. Debian 12 "bookworm" ships v252 and Ubuntu 22.04 LTS "jammy" ships v249.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the info, I updated the PR to explain this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines starting with # are comments in systemd. (Please keep up expecting software to be designed with common conventions in mind! That - reasonable - expectation is what keeps is from straying further into "surprise feature" territory.)

NotifyAccess=main
# the specific user that our service will run as
User=someuser
Expand All @@ -257,7 +258,8 @@ to the newly created unix socket:
RuntimeDirectory=gunicorn
WorkingDirectory=/home/someuser/applicationroot
ExecStart=/usr/bin/gunicorn applicationname.wsgi
ExecReload=/bin/kill -s HUP $MAINPID
# if 'Type=notify' instead of 'Type=notify-reload' (depending on systemd version)
# ExecReload=/bin/kill -s HUP $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
Expand Down
2 changes: 2 additions & 0 deletions gunicorn/arbiter.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,9 @@ def handle_hup(self):
- Gracefully shutdown the old worker processes
"""
self.log.info("Hang up: %s", self.master_name)
systemd.sd_notify("RELOADING=1\nSTATUS=Gunicorn arbiter reloading", self.log)
self.reload()
systemd.sd_notify("READY=1\nSTATUS=Gunicorn arbiter reloaded", self.log)

def handle_term(self):
"SIGTERM handling"
Expand Down
3 changes: 3 additions & 0 deletions gunicorn/systemd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import os
import socket
import time

SD_LISTEN_FDS_START = 3

Expand Down Expand Up @@ -66,6 +67,8 @@ def sd_notify(state, logger, unset_environment=False):
if addr[0] == '@':
addr = '\0' + addr[1:]
sock.connect(addr)
monotonic_usecs = time.clock_gettime_ns(time.CLOCK_MONOTONIC) // 1000
state = "%s\nMONOTONIC_USEC=%d" % (state, monotonic_usecs)
sock.sendall(state.encode('utf-8'))
except Exception:
logger.debug("Exception while invoking sd_notify()", exc_info=True)
Expand Down