|
|
@ -17,10 +17,10 @@ import gc |
|
|
|
import logging |
|
|
|
import logging |
|
|
|
import os |
|
|
|
import os |
|
|
|
import signal |
|
|
|
import signal |
|
|
|
|
|
|
|
import socket |
|
|
|
import sys |
|
|
|
import sys |
|
|
|
import traceback |
|
|
|
import traceback |
|
|
|
|
|
|
|
|
|
|
|
import sdnotify |
|
|
|
|
|
|
|
from daemonize import Daemonize |
|
|
|
from daemonize import Daemonize |
|
|
|
|
|
|
|
|
|
|
|
from twisted.internet import defer, error, reactor |
|
|
|
from twisted.internet import defer, error, reactor |
|
|
@ -246,13 +246,12 @@ def start(hs, listeners=None): |
|
|
|
def handle_sighup(*args, **kwargs): |
|
|
|
def handle_sighup(*args, **kwargs): |
|
|
|
# Tell systemd our state, if we're using it. This will silently fail if |
|
|
|
# Tell systemd our state, if we're using it. This will silently fail if |
|
|
|
# we're not using systemd. |
|
|
|
# we're not using systemd. |
|
|
|
sd_channel = sdnotify.SystemdNotifier() |
|
|
|
sdnotify(b"RELOADING=1") |
|
|
|
sd_channel.notify("RELOADING=1") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for i in _sighup_callbacks: |
|
|
|
for i in _sighup_callbacks: |
|
|
|
i(hs) |
|
|
|
i(hs) |
|
|
|
|
|
|
|
|
|
|
|
sd_channel.notify("READY=1") |
|
|
|
sdnotify(b"READY=1") |
|
|
|
|
|
|
|
|
|
|
|
signal.signal(signal.SIGHUP, handle_sighup) |
|
|
|
signal.signal(signal.SIGHUP, handle_sighup) |
|
|
|
|
|
|
|
|
|
|
@ -308,16 +307,12 @@ def setup_sdnotify(hs): |
|
|
|
|
|
|
|
|
|
|
|
# Tell systemd our state, if we're using it. This will silently fail if |
|
|
|
# Tell systemd our state, if we're using it. This will silently fail if |
|
|
|
# we're not using systemd. |
|
|
|
# we're not using systemd. |
|
|
|
sd_channel = sdnotify.SystemdNotifier() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hs.get_reactor().addSystemEventTrigger( |
|
|
|
hs.get_reactor().addSystemEventTrigger( |
|
|
|
"after", |
|
|
|
"after", "startup", sdnotify, b"READY=1\nMAINPID=%i" % (os.getpid(),) |
|
|
|
"startup", |
|
|
|
|
|
|
|
lambda: sd_channel.notify("READY=1\nMAINPID=%s" % (os.getpid())), |
|
|
|
|
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
hs.get_reactor().addSystemEventTrigger( |
|
|
|
hs.get_reactor().addSystemEventTrigger( |
|
|
|
"before", "shutdown", lambda: sd_channel.notify("STOPPING=1") |
|
|
|
"before", "shutdown", sdnotify, b"STOPPING=1" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -414,3 +409,35 @@ class _DeferredResolutionReceiver(object): |
|
|
|
def resolutionComplete(self): |
|
|
|
def resolutionComplete(self): |
|
|
|
self._deferred.callback(()) |
|
|
|
self._deferred.callback(()) |
|
|
|
self._receiver.resolutionComplete() |
|
|
|
self._receiver.resolutionComplete() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sdnotify_sockaddr = os.getenv("NOTIFY_SOCKET") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def sdnotify(state): |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
Send a notification to systemd, if the NOTIFY_SOCKET env var is set. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This function is based on the sdnotify python package, but since it's only a few |
|
|
|
|
|
|
|
lines of code, it's easier to duplicate it here than to add a dependency on a |
|
|
|
|
|
|
|
package which many OSes don't include as a matter of principle. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
|
|
|
state (bytes): notification to send |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
if not isinstance(state, bytes): |
|
|
|
|
|
|
|
raise TypeError("sdnotify should be called with a bytes") |
|
|
|
|
|
|
|
if not sdnotify_sockaddr: |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
addr = sdnotify_sockaddr |
|
|
|
|
|
|
|
if addr[0] == "@": |
|
|
|
|
|
|
|
addr = "\0" + addr[1:] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
|
|
|
with socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) as sock: |
|
|
|
|
|
|
|
sock.connect(addr) |
|
|
|
|
|
|
|
sock.sendall(state) |
|
|
|
|
|
|
|
except Exception as e: |
|
|
|
|
|
|
|
# this is a bit surprising, since we don't expect to have a NOTIFY_SOCKET |
|
|
|
|
|
|
|
# unless systemd is expecting us to notify it. |
|
|
|
|
|
|
|
logger.warning("Unable to send notification to systemd: %s", e) |
|
|
|