]> arthur.barton.de Git - ngircd-alex.git/commitdiff
Ping the service manager and set a status message
authorAlexander Barton <alex@barton.de>
Fri, 5 Apr 2024 20:48:22 +0000 (22:48 +0200)
committerAlexander Barton <alex@barton.de>
Fri, 5 Apr 2024 22:13:13 +0000 (00:13 +0200)
Periodically "ping" the service manager (every 3 seconds) and set a
status message showing connection statistics.

This enables using the systemd(8) watchdog functionality for the
"ngircd.service" unit.

contrib/ngircd.service
src/ngircd/conn.c
src/ngircd/sighandlers.c
src/ngircd/sighandlers.h

index 215f5052714806693d37fec4e32aefdcd70e7df1..5ab73553cffdc5e60328b95e6de5e2a44b64de3d 100644 (file)
@@ -37,6 +37,9 @@ EnvironmentFile=-/etc/default/ngircd-full-dbg
 # Start ngIRCd. Note: systemd doesn't allow to use $DAEMON here!
 ExecStart=/usr/sbin/ngircd --nodaemon --syslog $PARAMS
 ExecReload=/bin/kill -HUP $MAINPID
+# Error handling:
+# ngIRCd tries to "ping" the service manager every 3 seconds.
+WatchdogSec=10
 Restart=on-failure
 
 [Install]
index 61f296ab5d1e6c4359a302f744f9cbae88ce8568..b7838ea857e723cab0a16ee52d3f835d4ddc3e88 100644 (file)
@@ -669,8 +669,9 @@ Conn_Handler(void)
        int i;
        size_t wdatalen;
        struct timeval tv;
-       time_t t;
+       time_t t, notify_t = 0;
        bool command_available;
+       char status[200];
 
        Log(LOG_NOTICE, "Server \"%s\" (on \"%s\") ready.",
            Client_ID(Client_ThisServer()), Client_Hostname(Client_ThisServer()));
@@ -783,13 +784,24 @@ Conn_Handler(void)
                        exit(1);
                }
 
-               /* Should ngIRCd timeout when idle? */
+               t = time(NULL);
                if (Conf_IdleTimeout > 0 && NumConnectionsAccepted > 0
-                   && idle_t > 0 && time(NULL) - idle_t >= Conf_IdleTimeout) {
+                   && idle_t > 0 && t - idle_t >= Conf_IdleTimeout) {
+                       /* Should ngIRCd timeout when idle? */
                        LogDebug("Server idle timeout reached: %d second%s. Initiating shutdown ...",
                                 Conf_IdleTimeout,
                                 Conf_IdleTimeout == 1 ? "" : "s");
                        NGIRCd_SignalQuit = true;
+               } else if (Signal_NotifySvcMgr_Possible() && t - notify_t > 3) {
+                       /* Send the current status to the service manager. */
+                       snprintf(status, sizeof(status),
+                                "WATCHDOG=1\nSTATUS=%ld connection%s established (%ld user%s, %ld server%s), %ld maximum. %ld accepted in total.\n",
+                                NumConnections, NumConnections == 1 ? "" : "s",
+                                Client_MyUserCount(), Client_MyUserCount() == 1 ? "" : "s",
+                                Client_MyServerCount(), Client_MyServerCount() == 1 ? "" : "s",
+                                NumConnectionsMax, NumConnectionsAccepted);
+                       Signal_NotifySvcMgr(status);
+                       notify_t = t;
                }
        }
 
index 56fd8aea2382a6d588220eb3a7ba1a241384d989..00f5ae8555708e1c616f54a5263916a14311720b 100644 (file)
@@ -348,6 +348,21 @@ Signals_Exit(void)
        signalpipe[0] = signalpipe[1] = 0;
 }
 
+/**
+ * Check if the service manager of the system can be notified.
+ *
+ * @returns true if notifying the service manager is theoretically possible.
+ */
+GLOBAL bool
+Signal_NotifySvcMgr_Possible(void)
+{
+#if !defined(HAVE_SYS_UN_H) || !defined(SOCK_CLOEXEC)
+       return false;
+#else
+       return getenv("NOTIFY_SOCKET") != NULL;
+#endif
+}
+
 /**
  * Notify the service manager using the "sd_notify" protocol.
  *
index e03864a3d26bd9160f4cf5667c6282bb258c8f08..a7cafd1fd9a9ac3e605f43b23b6000566d9bcccc 100644 (file)
@@ -22,6 +22,7 @@
 bool Signals_Init PARAMS((void));
 void Signals_Exit PARAMS((void));
 
+GLOBAL bool Signal_NotifySvcMgr_Possible PARAMS((void));
 GLOBAL void Signal_NotifySvcMgr PARAMS((const char *message));
 
 #endif