diff --git a/doc/chronyd.adoc b/doc/chronyd.adoc index 887be48..dfabd3e 100644 --- a/doc/chronyd.adoc +++ b/doc/chronyd.adoc @@ -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_ diff --git a/examples/chronyd-restricted.service b/examples/chronyd-restricted.service index 30ba7d9..1894621 100644 --- a/examples/chronyd-restricted.service +++ b/examples/chronyd-restricted.service @@ -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 diff --git a/examples/chronyd.service b/examples/chronyd.service index a42eb92..e322454 100644 --- a/examples/chronyd.service +++ b/examples/chronyd.service @@ -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 864dec2..bf9c66b 100644 --- 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(""))