summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlexander Barton <alex@barton.de>2024-04-05 22:48:22 +0200
committerAlexander Barton <alex@barton.de>2024-04-06 00:13:13 +0200
commit791778d7b6e2f0e92c67e6812f85445171c24572 (patch)
tree8b52d2ab605fd52f1244ff5e3111c379773b0b8b
parente4873b4d63d0bcd4914a1cee82599a13cfd77e47 (diff)
downloadngircd-791778d7b6e2f0e92c67e6812f85445171c24572.tar.gz
ngircd-791778d7b6e2f0e92c67e6812f85445171c24572.zip
Ping the service manager and set a status message
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.
-rw-r--r--contrib/ngircd.service3
-rw-r--r--src/ngircd/conn.c18
-rw-r--r--src/ngircd/sighandlers.c15
-rw-r--r--src/ngircd/sighandlers.h1
4 files changed, 34 insertions, 3 deletions
diff --git a/contrib/ngircd.service b/contrib/ngircd.service
index 215f5052..5ab73553 100644
--- a/contrib/ngircd.service
+++ b/contrib/ngircd.service
@@ -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]
diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c
index 61f296ab..b7838ea8 100644
--- a/src/ngircd/conn.c
+++ b/src/ngircd/conn.c
@@ -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;
 		}
 	}
 
diff --git a/src/ngircd/sighandlers.c b/src/ngircd/sighandlers.c
index 56fd8aea..00f5ae85 100644
--- a/src/ngircd/sighandlers.c
+++ b/src/ngircd/sighandlers.c
@@ -349,6 +349,21 @@ Signals_Exit(void)
 }
 
 /**
+ * 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.
  *
  * This function is based on the example notify() function shown in the
diff --git a/src/ngircd/sighandlers.h b/src/ngircd/sighandlers.h
index e03864a3..a7cafd1f 100644
--- a/src/ngircd/sighandlers.h
+++ b/src/ngircd/sighandlers.h
@@ -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