[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

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