]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
main: add support for systemd notification
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 5 Feb 2025 08:30:46 +0000 (09:30 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Wed, 5 Feb 2025 15:10:04 +0000 (16:10 +0100)
On Linux, if the NOTIFY_SOCKET variable is set, send a "READY=1"
and "STOPPING=1" message to the Unix domain socket after initialization
and before finalization respectively. This is used with the systemd
"notify" service type as documented in the sd_notity(3) man page. It's
a recommended alternative to the "forking" service type, which does not
need the PID file to determine the main process.

Support pathname Unix sockets only. Abstract sockets don't seem to be
used by systemd for notifications since version 212.

Switch the example services to the notify type, but keep the PID
file. It's still useful to prevent start of other chronyd instances.
systemd doesn't seem to care about the content of the file and should
just remove it in case chronyd didn't terminate cleanly.

Suggested-by: Luca Boccassi <bluca@debian.org>
doc/chronyd.adoc
examples/chronyd-restricted.service
examples/chronyd.service
main.c

index 887be485a6399c5cf3ef16ee336a6051da1798fb..dfabd3e064c760c17df564fab11ef28b4b326940 100644 (file)
@@ -217,6 +217,14 @@ client requests until the service is able to handle them. The service manager
 sets the LISTEN_FDS environment variable to the number of passed file
 descriptors.
 
+*NOTIFY_SOCKET*::
+The systemd service manager sets this variable for services of the *notify*
+type. *chronyd* sends a message to this socket when it it is fully initialised
+and ready to accept commands (e.g. from *chronyc*), with the clock already set
+if using the *-s* option or *initstepslew* directive. It is an alternative to
+the *forking* service type, which does not need the PID file. *chronyd* needs
+to be started with the *-n* or *-d* option to not fork.
+
 == FILES
 
 _@SYSCONFDIR@/chrony.conf_
index 30ba7d9f55c5227939d5c4fe05d8f972d276a474..18946210c7bf43cc2ed419b7bae321cf0f51aa4f 100644 (file)
@@ -12,10 +12,10 @@ Conflicts=chronyd.service ntpd.service systemd-timesyncd.service
 ConditionCapability=CAP_SYS_TIME
 
 [Service]
-Type=forking
+Type=notify
 PIDFile=/run/chrony/chronyd.pid
 EnvironmentFile=-/etc/sysconfig/chronyd
-ExecStart=/usr/sbin/chronyd -U $OPTIONS
+ExecStart=/usr/sbin/chronyd -n -U $OPTIONS
 
 User=chrony
 LogsDirectory=chrony
index a42eb92a1ceaab394911a24a5fb280e5e44a919d..e322454371644789733c62ba9b47a65c216dc24e 100644 (file)
@@ -6,10 +6,10 @@ Conflicts=ntpd.service systemd-timesyncd.service
 ConditionCapability=CAP_SYS_TIME
 
 [Service]
-Type=forking
+Type=notify
 PIDFile=/run/chrony/chronyd.pid
 EnvironmentFile=-/etc/sysconfig/chronyd
-ExecStart=/usr/sbin/chronyd $OPTIONS
+ExecStart=/usr/sbin/chronyd -n $OPTIONS
 
 CapabilityBoundingSet=~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE
 CapabilityBoundingSet=~CAP_BLOCK_SUSPEND CAP_KILL CAP_LEASE CAP_LINUX_IMMUTABLE
diff --git a/main.c b/main.c
index 864dec2d3924d3a304d0868364c185261a3e9f48..bf9c66bf8ae4e3526ce11b325c35f5c5ab34cb4a 100644 (file)
--- a/main.c
+++ b/main.c
@@ -107,11 +107,40 @@ delete_pidfile(void)
 
 /* ================================================== */
 
+static void
+notify_system_manager(int start)
+{
+#ifdef LINUX
+  /* The systemd protocol is documented in the sd_notify(3) man page */
+  const char *message, *path = getenv("NOTIFY_SOCKET");
+  int sock_fd;
+
+  if (!path)
+    return;
+
+  if (path[0] != '/')
+    LOG_FATAL("Unsupported notification socket");
+
+  message = start ? "READY=1" : "STOPPING=1";
+
+  sock_fd = SCK_OpenUnixDatagramSocket(path, NULL, 0);
+
+  if (sock_fd < 0 || SCK_Send(sock_fd, message, strlen(message), 0) != strlen(message))
+    LOG_FATAL("Could not send notification");
+
+  SCK_CloseSocket(sock_fd);
+#endif
+}
+
+/* ================================================== */
+
 void
 MAI_CleanupAndExit(void)
 {
   if (!initialised) exit(exit_status);
   
+  notify_system_manager(0);
+
   LCL_CancelOffsetCorrection();
   SRC_DumpSources();
 
@@ -215,6 +244,8 @@ post_init_ntp_hook(void *anything)
     REF_SetMode(ref_mode);
   }
 
+  notify_system_manager(1);
+
   /* Send an empty message to the foreground process so it can exit.
      If that fails, indicating the process was killed, exit too. */
   if (!LOG_NotifyParent(""))