New configuration option "IdleTimeout": exit daemon when idle
authorAlexander Barton <alex@barton.de>
Mon, 4 Feb 2013 22:15:53 +0000 (23:15 +0100)
committerAlexander Barton <alex@barton.de>
Mon, 4 Feb 2013 22:15:53 +0000 (23:15 +0100)
This patch implements a new configuration option "IdleTimeout" in the
[Limits] section of the configuration file which can be used to set a
timeout (in seconds) after which the whole daemon will shutdown when no
more connections are left active after handling at least one client.

The default is 0, "never".

This can be useful for testing or when ngIRCd is started using "socket
activation" with systemd(8), for example.

doc/sample-ngircd.conf.tmpl
man/ngircd.conf.5.tmpl
src/ngircd/conf.c
src/ngircd/conf.h
src/ngircd/conn.c

index 1c3998ad61368fca9448013206c2cd35e5187779..822fd5d4fb9dd5b99f2694b5be98ce88075c68c5 100644 (file)
        # to not yet (or no longer) connected servers.
        ;ConnectRetry = 60
 
+       # Number of seconds after which the whole daemon should shutdown when
+       # no connections are left active after handling at least one client
+       # (0: never, which is the default).
+       # This can be useful for testing or when ngIRCd is started using
+       # "socket activation" with systemd(8), for example.
+       ;IdleTimeout = 0
+
        # Maximum number of simultaneous in- and outbound connections the
        # server is allowed to accept (0: unlimited):
        ;MaxConnections = 0
index 859c6a8ac0eb547b915e73fbed78cbf4e726c8a5..e5485dbf10edddc2c7c0532b79902bd696fedbc4 100644 (file)
@@ -1,7 +1,7 @@
 .\"
 .\" ngircd.conf(5) manual page template
 .\"
-.TH ngircd.conf 5 "Nov 2012" ngIRCd "ngIRCd Manual"
+.TH ngircd.conf 5 "Feb 2013" ngIRCd "ngIRCd Manual"
 .SH NAME
 ngircd.conf \- configuration file of ngIRCd
 .SH SYNOPSIS
@@ -170,6 +170,12 @@ should be safe, but it is wise to double-check :-)
 The server tries every <ConnectRetry> seconds to establish a link to not yet
 (or no longer) connected servers. Default: 60.
 .TP
+\fBIdleTimeout\fR (number)
+Number of seconds after which the whole daemon should shutdown when no
+connections are left active after handling at least one client (0: never). This
+can be useful for testing or when ngIRCd is started using "socket activation"
+with systemd(8), for example. Default: 0.
+.TP
 \fBMaxConnections\fR (number)
 Maximum number of simultaneous in- and outbound connections the server is
 allowed to accept (0: unlimited). Default: 0.
index 929ab05403734b8cd43e851955828072c38a0e33..835b5ea4e450b3ed262ebe82b1647f5870f495f6 100644 (file)
@@ -370,6 +370,7 @@ Conf_Test( void )
 
        puts("[LIMITS]");
        printf("  ConnectRetry = %d\n", Conf_ConnectRetry);
+       printf("  IdleTimeout = %d\n", Conf_IdleTimeout);
        printf("  MaxConnections = %d\n", Conf_MaxConnections);
        printf("  MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP);
        printf("  MaxJoins = %d\n", Conf_MaxJoins > 0 ? Conf_MaxJoins : -1);
@@ -736,6 +737,7 @@ Set_Defaults(bool InitServers)
 
        /* Limits */
        Conf_ConnectRetry = 60;
+       Conf_IdleTimeout = 0;
        Conf_MaxConnections = 0;
        Conf_MaxConnectionsIP = 5;
        Conf_MaxJoins = 10;
@@ -1241,6 +1243,7 @@ CheckLegacyGlobalOption(int Line, char *Var, char *Arg)
                return "[Options]";
        }
        if (strcasecmp(Var, "ConnectRetry") == 0
+           || strcasecmp(Var, "IdleTimeout") == 0
            || strcasecmp(Var, "MaxConnections") == 0
            || strcasecmp(Var, "MaxConnectionsIP") == 0
            || strcasecmp(Var, "MaxJoins") == 0
@@ -1490,6 +1493,12 @@ Handle_LIMITS(int Line, char *Var, char *Arg)
                }
                return;
        }
+       if (strcasecmp(Var, "IdleTimeout") == 0) {
+               Conf_IdleTimeout = atoi(Arg);
+               if (!Conf_IdleTimeout && strcmp(Arg, "0"))
+                       Config_Error_NaN(Line, Var);
+               return;
+       }
        if (strcasecmp(Var, "MaxConnections") == 0) {
                Conf_MaxConnections = atoi(Arg);
                if (!Conf_MaxConnections && strcmp(Arg, "0"))
index c203b57032a9558a3d3e6efcf44dad9019e5a355..bbf4f36c24c4ff29d1c2b3dc99ba58897f658443 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2013 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
@@ -211,6 +211,9 @@ GLOBAL bool Conf_ConnectIPv6;
 /** Try to connect to remote systems using the IPv4 protocol (true) */
 GLOBAL bool Conf_ConnectIPv4;
 
+/** Idle timout (seconds), after which the daemon should exit */
+GLOBAL int Conf_IdleTimeout;
+
 /** Maximum number of simultaneous connections to this server */
 GLOBAL int Conf_MaxConnections;
 
index 378509f96f09bc35eb9e3ebc2eb12140c24509fb..cfa67eafb8bd7e9fdac8cfc75b390ee1620ee705 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2013 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
@@ -121,6 +121,8 @@ static void cb_Read_Resolver_Result PARAMS((int sock, UNUSED short what));
 static void cb_Connect_to_Server PARAMS((int sock, UNUSED short what));
 static void cb_clientserver PARAMS((int sock, short what));
 
+time_t idle_t = 0;
+
 
 /**
  * Get number of sockets available from systemd(8).
@@ -906,6 +908,15 @@ Conn_Handler(void)
                            PACKAGE_NAME);
                        exit(1);
                }
+
+               /* Should ngIRCd timeout when idle? */
+               if (Conf_IdleTimeout > 0 && NumConnectionsAccepted > 0
+                   && idle_t > 0 && time(NULL) - idle_t >= Conf_IdleTimeout) {
+                       LogDebug("Server idle timeout reached: %d second%s. Initiating shutdown ...",
+                                Conf_IdleTimeout,
+                                Conf_IdleTimeout == 1 ? "" : "s");
+                       NGIRCd_SignalQuit = true;
+               }
        }
 
        if (NGIRCd_SignalQuit)
@@ -1267,6 +1278,8 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
                NumConnections--;
        LogDebug("Shutdown of connection %d completed, %ld connection%s left.",
                 Idx, NumConnections, NumConnections != 1 ? "s" : "");
+
+       idle_t = NumConnections > 0 ? 0 : time(NULL);
 } /* Conn_Close */
 
 
@@ -1638,6 +1651,7 @@ static void
 Account_Connection(void)
 {
        NumConnections++;
+       idle_t = 0;
        if (NumConnections > NumConnectionsMax)
                NumConnectionsMax = NumConnections;
        LogDebug("Total number of connections now %lu (max %lu).",