[BACK]Return to sighandlers.c CVS log [TXT][DIR] Up to [local] / ircnowd / src / ngircd

Annotation of ircnowd/src/ngircd/sighandlers.c, Revision 1.1

1.1     ! tomglok     1: /*
        !             2:  * ngIRCd -- The Next Generation IRC Daemon
        !             3:  * Copyright (c)2001-2015 Alexander Barton (alex@barton.de) and Contributors.
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify
        !             6:  * it under the terms of the GNU General Public License as published by
        !             7:  * the Free Software Foundation; either version 2 of the License, or
        !             8:  * (at your option) any later version.
        !             9:  * Please read the file COPYING, README and AUTHORS for more information.
        !            10:  */
        !            11:
        !            12: #include "portab.h"
        !            13:
        !            14: /**
        !            15:  * @file
        !            16:  * Signal Handlers: Actions to be performed when the program
        !            17:  * receives a signal.
        !            18:  */
        !            19:
        !            20: #include <errno.h>
        !            21: #include <unistd.h>
        !            22: #include <stdlib.h>
        !            23: #include <string.h>
        !            24: #include <signal.h>
        !            25: #include <sys/types.h>
        !            26: #include <sys/wait.h>
        !            27: #include <time.h>
        !            28:
        !            29: #include "conn.h"
        !            30: #include "channel.h"
        !            31: #include "conf.h"
        !            32: #include "io.h"
        !            33: #include "log.h"
        !            34: #include "ngircd.h"
        !            35:
        !            36: #include "sighandlers.h"
        !            37:
        !            38: static int signalpipe[2];
        !            39:
        !            40: static const int signals_catch[] = {
        !            41:        SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2
        !            42: };
        !            43:
        !            44: #ifdef DEBUG
        !            45:
        !            46: static void
        !            47: Dump_State(void)
        !            48: {
        !            49:        Log(LOG_DEBUG, "--- Internal server state: %s ---",
        !            50:            Client_ID(Client_ThisServer()));
        !            51: #ifdef HAVE_LONG_LONG
        !            52:        Log(LOG_DEBUG, "time()=%llu", (unsigned long long)time(NULL));
        !            53: #else
        !            54:        Log(LOG_DEBUG, "time()=%lu", (unsigned long)time(NULL));
        !            55: #endif
        !            56:        Conf_DebugDump();
        !            57:        Conn_DebugDump();
        !            58:        Client_DebugDump();
        !            59:        Log(LOG_DEBUG, "--- End of state dump ---");
        !            60: } /* Dump_State */
        !            61:
        !            62: #endif
        !            63:
        !            64: static void
        !            65: Signal_Block(int sig)
        !            66: {
        !            67: #ifdef HAVE_SIGPROCMASK
        !            68:        sigset_t set;
        !            69:
        !            70:        sigemptyset(&set);
        !            71:        sigaddset(&set, sig);
        !            72:
        !            73:        sigprocmask(SIG_BLOCK, &set, NULL);
        !            74: #else
        !            75:        sigblock(sig);
        !            76: #endif
        !            77: }
        !            78:
        !            79: static void
        !            80: Signal_Unblock(int sig)
        !            81: {
        !            82: #ifdef HAVE_SIGPROCMASK
        !            83:        sigset_t set;
        !            84:
        !            85:        sigemptyset(&set);
        !            86:        sigaddset(&set, sig);
        !            87:
        !            88:        sigprocmask(SIG_UNBLOCK, &set, NULL);
        !            89: #else
        !            90:        int old = sigblock(0) & ~sig;
        !            91:        sigsetmask(old);
        !            92: #endif
        !            93: }
        !            94:
        !            95: /**
        !            96:  * Reload the server configuration file.
        !            97:  */
        !            98: static void
        !            99: Rehash(void)
        !           100: {
        !           101:        char old_name[CLIENT_ID_LEN];
        !           102:        unsigned old_nicklen;
        !           103:
        !           104:        Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" );
        !           105:
        !           106:        /* Remember old server name and nickname length */
        !           107:        strlcpy( old_name, Conf_ServerName, sizeof old_name );
        !           108:        old_nicklen = Conf_MaxNickLength;
        !           109:
        !           110:        /* Re-read configuration ... */
        !           111:        if (!Conf_Rehash( ))
        !           112:                return;
        !           113:
        !           114:        /* Close down all listening sockets */
        !           115:        Conn_ExitListeners( );
        !           116:
        !           117:        /* Recover old server name and nickname length: these values can't
        !           118:         * be changed during run-time */
        !           119:        if (strcmp(old_name, Conf_ServerName) != 0 ) {
        !           120:                strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName);
        !           121:                Log(LOG_ERR,
        !           122:                    "Can't change server name (\"Name\") on runtime! Ignored new name.");
        !           123:        }
        !           124:        if (old_nicklen != Conf_MaxNickLength) {
        !           125:                Conf_MaxNickLength = old_nicklen;
        !           126:                Log(LOG_ERR,
        !           127:                    "Can't change \"MaxNickLength\" on runtime! Ignored new value.");
        !           128:        }
        !           129:
        !           130:        /* Create new pre-defined channels */
        !           131:        Channel_InitPredefined( );
        !           132:
        !           133:        if (!ConnSSL_InitLibrary())
        !           134:                Log(LOG_WARNING,
        !           135:                    "Re-Initializing of SSL failed!");
        !           136:
        !           137:        /* Start listening on sockets */
        !           138:        Conn_InitListeners( );
        !           139:
        !           140:        /* Sync configuration with established connections */
        !           141:        Conn_SyncServerStruct( );
        !           142:
        !           143:        Log( LOG_NOTICE|LOG_snotice, "Re-reading of configuration done." );
        !           144: } /* Rehash */
        !           145:
        !           146: /**
        !           147:  * Signal handler of ngIRCd.
        !           148:  * This function is called whenever ngIRCd catches a signal sent by the
        !           149:  * user and/or the system to it. For example SIGTERM and SIGHUP.
        !           150:  *
        !           151:  * It blocks the signal and queues it for later execution by Signal_Handler_BH.
        !           152:  * @param Signal Number of the signal to handle.
        !           153:  */
        !           154: static void
        !           155: Signal_Handler(int Signal)
        !           156: {
        !           157:        if (Signal != SIGCHLD) {
        !           158: #ifdef HAVE_STRSIGNAL
        !           159:                Log(LOG_INFO, "Got signal \"%s\" ...", strsignal(Signal));
        !           160: #else
        !           161:                Log(LOG_INFO, "Got signal %d ...", Signal);
        !           162: #endif
        !           163:        }
        !           164:
        !           165:        switch (Signal) {
        !           166:        case SIGTERM:
        !           167:        case SIGINT:
        !           168:        case SIGQUIT:
        !           169:                /* shut down sever */
        !           170:                NGIRCd_SignalQuit = true;
        !           171:                return;
        !           172:        case SIGCHLD:
        !           173:                /* child-process exited, avoid zombies */
        !           174:                while (waitpid( -1, NULL, WNOHANG) > 0)
        !           175:                        ;
        !           176:                return;
        !           177: #ifdef DEBUG
        !           178:        case SIGUSR1:
        !           179:                if (! NGIRCd_Debug) {
        !           180:                        Log(LOG_INFO|LOG_snotice,
        !           181:                            "Got SIGUSR1, debug mode activated.");
        !           182: #ifdef SNIFFER
        !           183:                        strcpy(NGIRCd_DebugLevel, "2");
        !           184:                        NGIRCd_Debug = true;
        !           185:                        NGIRCd_Sniffer = true;
        !           186: #else
        !           187:                        strcpy(NGIRCd_DebugLevel, "1");
        !           188:                        NGIRCd_Debug = true;
        !           189: #endif /* SNIFFER */
        !           190:                } else {
        !           191:                        Log(LOG_INFO|LOG_snotice,
        !           192:                            "Got SIGUSR1, debug mode deactivated.");
        !           193:                        strcpy(NGIRCd_DebugLevel, "");
        !           194:                        NGIRCd_Debug = false;
        !           195: #ifdef SNIFFER
        !           196:                        NGIRCd_Sniffer = false;
        !           197: #endif /* SNIFFER */
        !           198:                }
        !           199:                return;
        !           200: #endif
        !           201:        }
        !           202:
        !           203:        /*
        !           204:         * other signal: queue for later execution.
        !           205:         * This has the advantage that we are not restricted
        !           206:         * to functions that can be called safely from signal handlers.
        !           207:         */
        !           208:        if (write(signalpipe[1], &Signal, sizeof(Signal)) != -1)
        !           209:                Signal_Block(Signal);
        !           210: } /* Signal_Handler */
        !           211:
        !           212: /**
        !           213:  * Signal processing handler of ngIRCd.
        !           214:  * This function is called from the main conn event loop in (io_dispatch)
        !           215:  * whenever ngIRCd has queued a signal.
        !           216:  *
        !           217:  * This function runs in normal context, not from the real signal handler,
        !           218:  * thus its not necessary to only use functions that are signal safe.
        !           219:  * @param Signal Number of the signal that was queued.
        !           220:  */
        !           221: static void
        !           222: Signal_Handler_BH(int Signal)
        !           223: {
        !           224:        switch (Signal) {
        !           225:        case SIGHUP:
        !           226:                /* re-read configuration */
        !           227:                Rehash();
        !           228:                break;
        !           229: #ifdef DEBUG
        !           230:        case SIGUSR2:
        !           231:                if (NGIRCd_Debug) {
        !           232:                        Log(LOG_INFO|LOG_snotice,
        !           233:                            "Got SIGUSR2, dumping internal state ...");
        !           234:                        Dump_State();
        !           235:                }
        !           236:                break;
        !           237:        default:
        !           238:                Log(LOG_DEBUG, "Got signal %d! Ignored.", Signal);
        !           239: #endif
        !           240:        }
        !           241:        Signal_Unblock(Signal);
        !           242: }
        !           243:
        !           244: static void
        !           245: Signal_Callback(int fd, short UNUSED what)
        !           246: {
        !           247:        int sig, ret;
        !           248:        (void) what;
        !           249:
        !           250:        do {
        !           251:                ret = (int)read(fd, &sig, sizeof(sig));
        !           252:                if (ret == sizeof(int))
        !           253:                        Signal_Handler_BH(sig);
        !           254:        } while (ret == sizeof(int));
        !           255:
        !           256:        if (ret == -1) {
        !           257:                if (errno == EAGAIN || errno == EINTR)
        !           258:                        return;
        !           259:
        !           260:                Log(LOG_EMERG, "Read from signal pipe: %s - Exiting!",
        !           261:                    strerror(errno));
        !           262:                exit(1);
        !           263:        }
        !           264:
        !           265:        Log(LOG_EMERG, "EOF on signal pipe!? - Exiting!");
        !           266:        exit(1);
        !           267: }
        !           268:
        !           269: /**
        !           270:  * Initialize the signal handlers, catch
        !           271:  * those signals we are interested in and sets SIGPIPE to be ignored.
        !           272:  * @return true if initialization was successful.
        !           273:  */
        !           274: bool
        !           275: Signals_Init(void)
        !           276: {
        !           277:        size_t i;
        !           278: #ifdef HAVE_SIGACTION
        !           279:        struct sigaction saction;
        !           280: #endif
        !           281:        if (signalpipe[0] > 0 || signalpipe[1] > 0)
        !           282:                return true;
        !           283:
        !           284:        if (pipe(signalpipe))
        !           285:                return false;
        !           286:
        !           287:        if (!io_setnonblock(signalpipe[0]) ||
        !           288:            !io_setnonblock(signalpipe[1]))
        !           289:                return false;
        !           290:        if (!io_setcloexec(signalpipe[0]) ||
        !           291:            !io_setcloexec(signalpipe[1]))
        !           292:                return false;
        !           293: #ifdef HAVE_SIGACTION
        !           294:        memset( &saction, 0, sizeof( saction ));
        !           295:        saction.sa_handler = Signal_Handler;
        !           296: #ifdef SA_RESTART
        !           297:        saction.sa_flags |= SA_RESTART;
        !           298: #endif
        !           299: #ifdef SA_NOCLDWAIT
        !           300:        saction.sa_flags |= SA_NOCLDWAIT;
        !           301: #endif
        !           302:
        !           303:        for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
        !           304:                sigaction(signals_catch[i], &saction, NULL);
        !           305:
        !           306:        /* we handle write errors properly; ignore SIGPIPE */
        !           307:        saction.sa_handler = SIG_IGN;
        !           308:        sigaction(SIGPIPE, &saction, NULL);
        !           309: #else
        !           310:        for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
        !           311:                signal(signals_catch[i], Signal_Handler);
        !           312:
        !           313:        signal(SIGPIPE, SIG_IGN);
        !           314: #endif
        !           315:        return io_event_create(signalpipe[0], IO_WANTREAD, Signal_Callback);
        !           316: } /* Signals_Init */
        !           317:
        !           318: /**
        !           319:  * Restores signals to their default behavior.
        !           320:  *
        !           321:  * This should be called after a fork() in the new
        !           322:  * child prodcess, especially when we are about to call
        !           323:  * 3rd party code (e.g. PAM).
        !           324:  */
        !           325: void
        !           326: Signals_Exit(void)
        !           327: {
        !           328:        size_t i;
        !           329: #ifdef HAVE_SIGACTION
        !           330:        struct sigaction saction;
        !           331:
        !           332:        memset(&saction, 0, sizeof(saction));
        !           333:        saction.sa_handler = SIG_DFL;
        !           334:
        !           335:        for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
        !           336:                sigaction(signals_catch[i], &saction, NULL);
        !           337:        sigaction(SIGPIPE, &saction, NULL);
        !           338: #else
        !           339:        for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
        !           340:                signal(signals_catch[i], SIG_DFL);
        !           341:        signal(SIGPIPE, SIG_DFL);
        !           342: #endif
        !           343:        close(signalpipe[1]);
        !           344:        close(signalpipe[0]);
        !           345:        signalpipe[0] = signalpipe[1] = 0;
        !           346: }
        !           347:
        !           348: /* -eof- */

CVSweb