1
0
mirror of https://github.com/osmarks/ngircd.git synced 2024-12-11 17:30:29 +00:00

Add support for the "sd_notify" protocol

This allows the "ngircd.service" systemd(8) unit to use the "notify"
service type, which allows for better status tracking by the service
manager.
This commit is contained in:
Alexander Barton 2024-04-05 22:38:22 +02:00
parent 3e535a2955
commit e4873b4d63
5 changed files with 110 additions and 7 deletions

View File

@ -193,6 +193,7 @@ AC_CHECK_HEADERS_ONCE([ \
stddef.h \ stddef.h \
stdint.h \ stdint.h \
sys/resource.h \ sys/resource.h \
sys/un.h \
varargs.h \ varargs.h \
]) ])

View File

@ -11,7 +11,7 @@ Before=anope.service atheme.service irc-services.service
Before=bopm.service hopm.service Before=bopm.service hopm.service
[Service] [Service]
Type=forking Type=notify
User=irc User=irc
Group=irc Group=irc
# Settings & limits: # Settings & limits:
@ -35,7 +35,7 @@ EnvironmentFile=-/etc/default/ngircd
EnvironmentFile=-/etc/default/ngircd-full EnvironmentFile=-/etc/default/ngircd-full
EnvironmentFile=-/etc/default/ngircd-full-dbg EnvironmentFile=-/etc/default/ngircd-full-dbg
# Start ngIRCd. Note: systemd doesn't allow to use $DAEMON here! # Start ngIRCd. Note: systemd doesn't allow to use $DAEMON here!
ExecStart=/usr/sbin/ngircd $PARAMS ExecStart=/usr/sbin/ngircd --nodaemon --syslog $PARAMS
ExecReload=/bin/kill -HUP $MAINPID ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure Restart=on-failure

View File

@ -66,6 +66,7 @@
#include "ng_ipaddr.h" #include "ng_ipaddr.h"
#include "parse.h" #include "parse.h"
#include "resolve.h" #include "resolve.h"
#include "sighandlers.h"
#define SERVER_WAIT (NONE - 1) /** "Wait for outgoing connection" flag */ #define SERVER_WAIT (NONE - 1) /** "Wait for outgoing connection" flag */
@ -673,6 +674,7 @@ Conn_Handler(void)
Log(LOG_NOTICE, "Server \"%s\" (on \"%s\") ready.", Log(LOG_NOTICE, "Server \"%s\" (on \"%s\") ready.",
Client_ID(Client_ThisServer()), Client_Hostname(Client_ThisServer())); Client_ID(Client_ThisServer()), Client_Hostname(Client_ThisServer()));
Signal_NotifySvcMgr("READY=1\n");
while (!NGIRCd_SignalQuit && !NGIRCd_SignalRestart) { while (!NGIRCd_SignalQuit && !NGIRCd_SignalRestart) {
t = time(NULL); t = time(NULL);
@ -791,10 +793,13 @@ Conn_Handler(void)
} }
} }
if (NGIRCd_SignalQuit) if (NGIRCd_SignalQuit) {
Log(LOG_NOTICE | LOG_snotice, "Server going down NOW!"); Log(LOG_NOTICE | LOG_snotice, "Server going down NOW!");
else if (NGIRCd_SignalRestart) Signal_NotifySvcMgr("STOPPING=1\n");
} else if (NGIRCd_SignalRestart) {
Log(LOG_NOTICE | LOG_snotice, "Server restarting NOW!"); Log(LOG_NOTICE | LOG_snotice, "Server restarting NOW!");
Signal_NotifySvcMgr("RELOADING=1\n");
}
} /* Conn_Handler */ } /* Conn_Handler */
/** /**

View File

@ -1,6 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors. * Copyright (c)2001-2024 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -26,6 +26,11 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <time.h> #include <time.h>
#ifdef HAVE_SYS_UN_H
# include <sys/socket.h>
# include <sys/un.h>
#endif
#include "conn.h" #include "conn.h"
#include "channel.h" #include "channel.h"
#include "conf.h" #include "conf.h"
@ -100,14 +105,17 @@ Rehash(void)
unsigned old_nicklen; unsigned old_nicklen;
Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" ); Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" );
Signal_NotifySvcMgr("RELOADING=1\n");
/* Remember old server name and nickname length */ /* Remember old server name and nickname length */
strlcpy( old_name, Conf_ServerName, sizeof old_name ); strlcpy( old_name, Conf_ServerName, sizeof old_name );
old_nicklen = Conf_MaxNickLength; old_nicklen = Conf_MaxNickLength;
/* Re-read configuration ... */ /* Re-read configuration ... */
if (!Conf_Rehash( )) if (!Conf_Rehash()) {
Signal_NotifySvcMgr("READY=1\n");
return; return;
}
/* Close down all listening sockets */ /* Close down all listening sockets */
Conn_ExitListeners( ); Conn_ExitListeners( );
@ -139,6 +147,7 @@ Rehash(void)
Conn_SyncServerStruct( ); Conn_SyncServerStruct( );
Log( LOG_NOTICE|LOG_snotice, "Re-reading of configuration done." ); Log( LOG_NOTICE|LOG_snotice, "Re-reading of configuration done." );
Signal_NotifySvcMgr("READY=1\n");
} /* Rehash */ } /* Rehash */
/** /**
@ -339,4 +348,89 @@ Signals_Exit(void)
signalpipe[0] = signalpipe[1] = 0; signalpipe[0] = signalpipe[1] = 0;
} }
/* -eof- */ /**
* Notify the service manager using the "sd_notify" protocol.
*
* This function is based on the example notify() function shown in the
* sd_notify(3) manual page, with one significant difference: we keep the file
* descriptor open to reduce overhead when called multiple times.
*
* @param message: The message to pass to the service manager including "\n".
*/
GLOBAL void
#if !defined(HAVE_SYS_UN_H) || !defined(SOCK_CLOEXEC)
Signal_NotifySvcMgr(UNUSED const char *message)
{
return;
#else
Signal_NotifySvcMgr(const char *message)
{
struct sockaddr_un socket_addr;
const char *socket_path;
size_t path_length, message_length;
static int fd = NONE;
assert(message != NULL);
assert(message[0] != '\0');
if (fd == NONE) {
/* No socket to the service manager open: Check if a path name
* is given in the environment and try to open it! */
socket_path = getenv("NOTIFY_SOCKET");
if (!socket_path)
return; /* No socket specified, nothing to do. */
/* Only AF_UNIX is supported, with path or abstract sockets */
if (socket_path[0] != '/' && socket_path[0] != '@') {
Log(LOG_CRIT,
"Failed to notify service manager: Unsupported socket path!");
return;
}
path_length = strlen(socket_path);
/* Ensure there is room for NUL byte */
if (path_length >= sizeof(socket_addr.sun_path)) {
Log(LOG_CRIT,
"Failed to notify service manager: Socket path too long!");
return;
}
memset(&socket_addr, 0, sizeof(struct sockaddr_un));
socket_addr.sun_family = AF_UNIX;
memcpy(socket_addr.sun_path, socket_path, path_length);
/* Support for abstract socket */
if (socket_addr.sun_path[0] == '@')
socket_addr.sun_path[0] = 0;
fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (fd < 0) {
Log(LOG_CRIT,
"Failed to notify service manager: %s [socket()]",
strerror(errno));
return;
}
if (connect(fd, (struct sockaddr *)&socket_addr,
sizeof(struct sockaddr_un)) != 0) {
Log(LOG_CRIT,
"Failed to notify service manager: %s [connect()]",
strerror(errno));
close(fd);
fd = NONE;
return;
}
}
message_length = strlen(message);
ssize_t written = write(fd, message, message_length);
if (written != (ssize_t)message_length) {
Log(LOG_CRIT,
"Failed to notify service manager: %s [write()]",
strerror(errno));
close(fd);
fd = NONE;
}
#endif
}

View File

@ -1,5 +1,6 @@
/* /*
* ngIRCd -- The Next Generation IRC Daemon * ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2024 Alexander Barton (alex@barton.de) and Contributors.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -21,6 +22,8 @@
bool Signals_Init PARAMS((void)); bool Signals_Init PARAMS((void));
void Signals_Exit PARAMS((void)); void Signals_Exit PARAMS((void));
GLOBAL void Signal_NotifySvcMgr PARAMS((const char *message));
#endif #endif
/* -eof- */ /* -eof- */