X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fsighandlers.c;h=8275123e6acd433a555f4e130a11faa10205ab47;hp=8f0a5a1b8cd3c8b1fd4a193af8a7c38119d21315;hb=HEAD;hpb=48326e061aacd954e24f76c53ded10448cbc28eb diff --git a/src/ngircd/sighandlers.c b/src/ngircd/sighandlers.c index 8f0a5a1b..00f5ae85 100644 --- a/src/ngircd/sighandlers.c +++ b/src/ngircd/sighandlers.c @@ -1,5 +1,6 @@ /* * 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 * it under the terms of the GNU General Public License as published by @@ -23,15 +24,20 @@ #include #include #include +#include + +#ifdef HAVE_SYS_UN_H +# include +# include +#endif -#include "imp.h" #include "conn.h" -#include "conf-ssl.h" #include "channel.h" #include "conf.h" #include "io.h" #include "log.h" #include "ngircd.h" + #include "sighandlers.h" static int signalpipe[2]; @@ -41,22 +47,22 @@ static const int signals_catch[] = { }; -#ifdef DEBUG - static void Dump_State(void) { - Log(LOG_DEBUG, "--- Internal server state: %s ---", + LogDebug("--- Internal server state: %s ---", Client_ID(Client_ThisServer())); - Log(LOG_DEBUG, "time()=%ld", time(NULL)); +#ifdef HAVE_LONG_LONG + LogDebug("time()=%llu", (unsigned long long)time(NULL)); +#else + LogDebug("time()=%lu", (unsigned long)time(NULL)); +#endif Conf_DebugDump(); Conn_DebugDump(); Client_DebugDump(); - Log(LOG_DEBUG, "--- End of state dump ---"); + LogDebug("--- End of state dump ---"); } /* Dump_State */ -#endif - static void Signal_Block(int sig) @@ -73,7 +79,6 @@ Signal_Block(int sig) #endif } - static void Signal_Unblock(int sig) { @@ -90,7 +95,6 @@ Signal_Unblock(int sig) #endif } - /** * Reload the server configuration file. */ @@ -101,14 +105,17 @@ Rehash(void) unsigned old_nicklen; Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" ); + Signal_NotifySvcMgr("RELOADING=1\n"); /* Remember old server name and nickname length */ strlcpy( old_name, Conf_ServerName, sizeof old_name ); old_nicklen = Conf_MaxNickLength; /* Re-read configuration ... */ - if (!Conf_Rehash( )) + if (!Conf_Rehash()) { + Signal_NotifySvcMgr("READY=1\n"); return; + } /* Close down all listening sockets */ Conn_ExitListeners( ); @@ -117,18 +124,21 @@ Rehash(void) * be changed during run-time */ if (strcmp(old_name, Conf_ServerName) != 0 ) { strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName); - Log(LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name."); + Log(LOG_ERR, + "Can't change server name (\"Name\") on runtime! Ignored new name."); } if (old_nicklen != Conf_MaxNickLength) { Conf_MaxNickLength = old_nicklen; - Log(LOG_ERR, "Can't change \"MaxNickLength\" on runtime! Ignored new value."); + Log(LOG_ERR, + "Can't change \"MaxNickLength\" on runtime! Ignored new value."); } /* Create new pre-defined channels */ Channel_InitPredefined( ); if (!ConnSSL_InitLibrary()) - Log(LOG_WARNING, "Re-Initializing SSL failed, using old keys"); + Log(LOG_WARNING, + "Re-Initializing of SSL failed!"); /* Start listening on sockets */ Conn_InitListeners( ); @@ -137,9 +147,9 @@ Rehash(void) Conn_SyncServerStruct( ); Log( LOG_NOTICE|LOG_snotice, "Re-reading of configuration done." ); + Signal_NotifySvcMgr("READY=1\n"); } /* Rehash */ - /** * Signal handler of ngIRCd. * This function is called whenever ngIRCd catches a signal sent by the @@ -151,6 +161,14 @@ Rehash(void) static void Signal_Handler(int Signal) { + if (Signal != SIGCHLD) { +#ifdef HAVE_STRSIGNAL + Log(LOG_INFO, "Got signal \"%s\" ...", strsignal(Signal)); +#else + Log(LOG_INFO, "Got signal %d ...", Signal); +#endif + } + switch (Signal) { case SIGTERM: case SIGINT: @@ -163,7 +181,6 @@ Signal_Handler(int Signal) while (waitpid( -1, NULL, WNOHANG) > 0) ; return; -#ifdef DEBUG case SIGUSR1: if (! NGIRCd_Debug) { Log(LOG_INFO|LOG_snotice, @@ -186,7 +203,6 @@ Signal_Handler(int Signal) #endif /* SNIFFER */ } return; -#endif } /* @@ -198,7 +214,6 @@ Signal_Handler(int Signal) Signal_Block(Signal); } /* Signal_Handler */ - /** * Signal processing handler of ngIRCd. * This function is called from the main conn event loop in (io_dispatch) @@ -216,7 +231,6 @@ Signal_Handler_BH(int Signal) /* re-read configuration */ Rehash(); break; -#ifdef DEBUG case SIGUSR2: if (NGIRCd_Debug) { Log(LOG_INFO|LOG_snotice, @@ -225,13 +239,11 @@ Signal_Handler_BH(int Signal) } break; default: - Log(LOG_DEBUG, "Got signal %d! Ignored.", Signal); -#endif + LogDebug("Got signal %d! Ignored.", Signal); } Signal_Unblock(Signal); } - static void Signal_Callback(int fd, short UNUSED what) { @@ -248,19 +260,19 @@ Signal_Callback(int fd, short UNUSED what) if (errno == EAGAIN || errno == EINTR) return; - Log(LOG_EMERG, "read from signal pipe: %s", strerror(errno)); + Log(LOG_EMERG, "Read from signal pipe: %s - Exiting!", + strerror(errno)); exit(1); } - Log(LOG_EMERG, "EOF on signal pipe"); + Log(LOG_EMERG, "EOF on signal pipe!? - Exiting!"); exit(1); } - /** * Initialize the signal handlers, catch * those signals we are interested in and sets SIGPIPE to be ignored. - * @return true if initialization was sucessful. + * @return true if initialization was successful. */ bool Signals_Init(void) @@ -306,9 +318,8 @@ Signals_Init(void) return io_event_create(signalpipe[0], IO_WANTREAD, Signal_Callback); } /* Signals_Init */ - /** - * Restores signals to their default behaviour. + * Restores signals to their default behavior. * * This should be called after a fork() in the new * child prodcess, especially when we are about to call @@ -337,4 +348,104 @@ Signals_Exit(void) signalpipe[0] = signalpipe[1] = 0; } -/* -eof- */ +/** + * 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 + * 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 +}