Understanding How systemd Requests Configuration Reloads in Units: The Underlying Mechanism and API Details


3 views

When you execute systemctl reload, systemd initiates a specific procedure to request configuration reloads from units. The process works through a well-defined API pathway:

/* Simplified sequence in systemd's internal implementation */
1. systemd sends SIGHUP signal to the main process of the unit
2. For Type=notify services, systemd expects a READY=1 notification
3. The unit's ExecReload= command is executed if defined
4. systemd verifies the unit remains in active state

systemd checks multiple factors to determine if a unit supports reload:

  • Presence of ExecReload= in the unit file
  • Service type (e.g., Type=notify services often support reload)
  • Signal handling capability (SIGHUP)

Example unit file with reload support:

[Unit]
Description=NGINX web server

[Service]
Type=notify
ExecStart=/usr/sbin/nginx -g "daemon off;"
ExecReload=/usr/sbin/nginx -s reload
KillMode=process
Restart=on-failure

systemd uses D-Bus as its primary IPC mechanism for reload requests. The exact API call flows through:

/* D-Bus method call example (simplified) */
const char *unit = "nginx.service";
sd_bus_message *m = NULL;
sd_bus_call_method(bus,
                  "org.freedesktop.systemd1",
                  "/org/freedesktop/systemd1",
                  "org.freedesktop.systemd1.Manager",
                  "ReloadUnit",
                  NULL,
                  NULL,
                  "ss",
                  unit,
                  "replace");
Operation Process Impact Downtime Configuration Persistence
Reload Existing process continues None New config loaded
Restart New process created Brief interruption Complete reinitialization

To check if a service properly handles reload:

# Check unit file for reload capability
systemctl cat nginx.service | grep ExecReload

# Test the reload operation with tracing
strace -p $(pidof nginx) -e signal -s 100

When executing systemctl reload, systemd communicates with units through D-Bus, Linux's inter-process communication system. Here's the technical breakdown:

# Systemd's internal D-Bus call for reload:
dbus-send --system --dest=org.freedesktop.systemd1 \
/org/freedesktop/systemd1/unit/nginx_2eservice \
org.freedesktop.systemd1.Unit.Reload

This sends a signal to the unit's control process through the systemd manager. The actual implementation differs based on unit type:

  • Service units: Sends SIGHUP to the main process
  • Socket units: Re-parses socket configuration files
  • Mount units: Re-reads fstab entries

Systemd determines reload capability through three mechanisms:

  1. Unit file directives:
    [Service]
    ExecReload=/usr/sbin/nginx -s reload
    ReloadSignal=SIGHUP
  2. Type-specific defaults (e.g., notify services automatically support reload)
  3. D-Bus introspection checking for Reload() method existence

For custom services, implement reload properly:

# Python service example with reload handler
import signal
import systemd.daemon

def handle_reload(signum, frame):
    # Re-read config here
    load_configuration()

signal.signal(signal.SIGHUP, handle_reload)
systemd.daemon.notify('READY=1')

For traditional init scripts, use this wrapper:

#!/bin/bash
case "$1" in
    reload)
        kill -HUP $(cat /var/run/service.pid)
        ;;
esac

Debug reload issues with:

# Check reload support
systemctl show -p CanReload nginx.service

# Verify D-Bus methods
busctl introspect org.freedesktop.systemd1 \
/org/freedesktop/systemd1/unit/nginx_2eservice

Common pitfalls include:

  • Missing ExecReload directive for custom services
  • Configuration errors causing silent reload failures
  • PID file mismatches after reload