Annotation of embedaddon/quagga/lib/sigevent.c, revision 1.1.1.3

1.1       misho       1: /* Quagga signal handling functions.
                      2:  * Copyright (C) 2004 Paul Jakma,
                      3:  *
                      4:  * This file is part of Quagga.
                      5:  *
                      6:  * Quagga is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2, or (at your option) any
                      9:  * later version.
                     10:  *
                     11:  * Quagga is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     13:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     14:  * General Public License for more details.
                     15:  *
                     16:  * You should have received a copy of the GNU General Public License
                     17:  * along with Quagga; see the file COPYING.  If not, write to the Free
                     18:  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
                     19:  * 02111-1307, USA.  
                     20:  */
                     21: 
                     22: #include <zebra.h>
                     23: #include <sigevent.h>
                     24: #include <log.h>
1.1.1.2   misho      25: #include <memory.h>
1.1       misho      26: 
                     27: #ifdef SA_SIGINFO
                     28: #ifdef HAVE_UCONTEXT_H
                     29: #ifdef GNU_LINUX
                     30: /* get REG_EIP from ucontext.h */
                     31: #ifndef __USE_GNU
                     32: #define __USE_GNU
                     33: #endif /* __USE_GNU */
                     34: #endif /* GNU_LINUX */
                     35: #include <ucontext.h>
                     36: #endif /* HAVE_UCONTEXT_H */
                     37: #endif /* SA_SIGINFO */
                     38: 
                     39: 
                     40: /* master signals descriptor struct */
                     41: struct quagga_sigevent_master_t
                     42: {
                     43:   struct thread *t;
                     44: 
                     45:   struct quagga_signal_t *signals; 
                     46:   int sigc;
                     47:   
                     48:   volatile sig_atomic_t caught;
                     49: } sigmaster;
                     50: 
                     51: /* Generic signal handler 
                     52:  * Schedules signal event thread
                     53:  */
                     54: static void
                     55: quagga_signal_handler (int signo)
                     56: {
                     57:   int i;
                     58:   struct quagga_signal_t *sig;
                     59:   
                     60:   for (i = 0; i < sigmaster.sigc; i++)
                     61:     {
                     62:       sig = &(sigmaster.signals[i]);
                     63:       
                     64:       if (sig->signal == signo)
                     65:         sig->caught = 1;
                     66:     }
                     67:   
                     68:   sigmaster.caught = 1;
                     69: } 
                     70: 
                     71: /* check if signals have been caught and run appropriate handlers */
                     72: int
                     73: quagga_sigevent_process (void)
                     74: {
                     75:   struct quagga_signal_t *sig;
                     76:   int i;
                     77: #ifdef SIGEVENT_BLOCK_SIGNALS
                     78:   /* shouldnt need to block signals, but potentially may be needed */
                     79:   sigset_t newmask, oldmask;
                     80: 
                     81:   /*
                     82:    * Block most signals, but be careful not to defer SIGTRAP because
                     83:    * doing so breaks gdb, at least on NetBSD 2.0.  Avoid asking to
                     84:    * block SIGKILL, just because we shouldn't be able to do so.
                     85:    */
                     86:   sigfillset (&newmask);
                     87:   sigdelset (&newmask, SIGTRAP);
                     88:   sigdelset (&newmask, SIGKILL);
                     89:    
                     90:   if ( (sigprocmask (SIG_BLOCK, &newmask, &oldmask)) < 0)
                     91:     {
                     92:       zlog_err ("quagga_signal_timer: couldnt block signals!");
                     93:       return -1;
                     94:     }
                     95: #endif /* SIGEVENT_BLOCK_SIGNALS */
                     96: 
                     97:   if (sigmaster.caught > 0)
                     98:     {
                     99:       sigmaster.caught = 0;
                    100:       /* must not read or set sigmaster.caught after here,
                    101:        * race condition with per-sig caught flags if one does
                    102:        */
                    103:       
                    104:       for (i = 0; i < sigmaster.sigc; i++)
                    105:         {
                    106:           sig = &(sigmaster.signals[i]);
                    107: 
                    108:           if (sig->caught > 0)
                    109:             {
                    110:               sig->caught = 0;
                    111:               sig->handler ();
                    112:             }
                    113:         }
                    114:     }
                    115: 
                    116: #ifdef SIGEVENT_BLOCK_SIGNALS
                    117:   if ( sigprocmask (SIG_UNBLOCK, &oldmask, NULL) < 0 );
                    118:     return -1;
                    119: #endif /* SIGEVENT_BLOCK_SIGNALS */
                    120: 
                    121:   return 0;
                    122: }
                    123: 
                    124: #ifdef SIGEVENT_SCHEDULE_THREAD
                    125: /* timer thread to check signals. Shouldnt be needed */
                    126: int
                    127: quagga_signal_timer (struct thread *t)
                    128: {
                    129:   struct quagga_sigevent_master_t *sigm;
                    130:   struct quagga_signal_t *sig;
                    131:   int i;
                    132: 
                    133:   sigm = THREAD_ARG (t);
                    134:   sigm->t = thread_add_timer (sigm->t->master, quagga_signal_timer, &sigmaster,
                    135:                               QUAGGA_SIGNAL_TIMER_INTERVAL);
                    136:   return quagga_sigevent_process ();
                    137: }
                    138: #endif /* SIGEVENT_SCHEDULE_THREAD */
                    139: 
                    140: /* Initialization of signal handles. */
                    141: /* Signal wrapper. */
                    142: static int
                    143: signal_set (int signo)
                    144: {
                    145:   int ret;
                    146:   struct sigaction sig;
                    147:   struct sigaction osig;
                    148: 
                    149:   sig.sa_handler = &quagga_signal_handler;
                    150:   sigfillset (&sig.sa_mask);
                    151:   sig.sa_flags = 0;
                    152:   if (signo == SIGALRM) {
                    153: #ifdef SA_INTERRUPT
                    154:       sig.sa_flags |= SA_INTERRUPT; /* SunOS */
                    155: #endif
                    156:   } else {
                    157: #ifdef SA_RESTART
                    158:       sig.sa_flags |= SA_RESTART;
                    159: #endif /* SA_RESTART */
                    160:   }
                    161: 
                    162:   ret = sigaction (signo, &sig, &osig);
                    163:   if (ret < 0) 
                    164:     return ret;
                    165:   else
                    166:     return 0;
                    167: }
                    168: 
                    169: #ifdef SA_SIGINFO
                    170: 
                    171: /* XXX This function should be enhanced to support more platforms
                    172:        (it currently works only on Linux/x86). */
                    173: static void *
                    174: program_counter(void *context)
                    175: {
                    176: #ifdef HAVE_UCONTEXT_H
                    177: #ifdef GNU_LINUX
1.1.1.3 ! misho     178:   /* these are from GNU libc, rather than Linux, strictly speaking */
        !           179: # if defined(REG_EIP)
        !           180: #  define REG_INDEX REG_EIP
        !           181: # elif defined(REG_RIP)
        !           182: #  define REG_INDEX REG_RIP
        !           183: # elif defined(__powerpc__)
        !           184: #  define REG_INDEX 32
        !           185: # endif
        !           186: #elif defined(SUNOS_5) /* !GNU_LINUX */
        !           187: # define REG_INDEX REG_PC
1.1       misho     188: #endif /* GNU_LINUX */
1.1.1.3 ! misho     189: 
        !           190: #ifdef REG_INDEX
        !           191: # ifdef HAVE_UCONTEXT_T_UC_MCONTEXT_GREGS
        !           192: #  define REGS gregs[REG_INDEX]
        !           193: # elif defined(HAVE_UCONTEXT_T_UC_MCONTEXT_UC_REGS)
        !           194: #  define REGS uc_regs->gregs[REG_INDEX]
        !           195: # endif /* HAVE_UCONTEXT_T_UC_MCONTEXT_GREGS */
        !           196: #endif /* REG_INDEX */
        !           197: 
        !           198: #ifdef REGS
        !           199:   if (context)
        !           200:     return (void *)(((ucontext_t *)context)->uc_mcontext.REGS);
        !           201: #elif defined(HAVE_UCONTEXT_T_UC_MCONTEXT_REGS__NIP) 
        !           202:   /* older Linux / struct pt_regs ? */
        !           203:   if (context)
        !           204:     return (void *)(((ucontext_t *)context)->uc_mcontext.regs->nip);
        !           205: #endif /* REGS */
        !           206: 
1.1       misho     207: #endif /* HAVE_UCONTEXT_H */
                    208:   return NULL;
                    209: }
                    210: 
                    211: #endif /* SA_SIGINFO */
                    212: 
                    213: static void __attribute__ ((noreturn))
                    214: exit_handler(int signo
                    215: #ifdef SA_SIGINFO
                    216:             , siginfo_t *siginfo, void *context
                    217: #endif
                    218:            )
                    219: {
                    220:   zlog_signal(signo, "exiting..."
                    221: #ifdef SA_SIGINFO
                    222:              , siginfo, program_counter(context)
                    223: #endif
                    224:             );
                    225:   _exit(128+signo);
                    226: }
                    227: 
                    228: static void __attribute__ ((noreturn))
                    229: core_handler(int signo
                    230: #ifdef SA_SIGINFO
                    231:             , siginfo_t *siginfo, void *context
                    232: #endif
                    233:            )
                    234: {
                    235:   zlog_signal(signo, "aborting..."
                    236: #ifdef SA_SIGINFO
                    237:              , siginfo, program_counter(context)
                    238: #endif
                    239:             );
                    240:   abort();
                    241: }
                    242: 
                    243: static void
                    244: trap_default_signals(void)
                    245: {
                    246:   static const int core_signals[] = {
                    247:     SIGQUIT,
                    248:     SIGILL,
                    249: #ifdef SIGEMT
                    250:     SIGEMT,
                    251: #endif
                    252:     SIGFPE,
                    253:     SIGBUS,
                    254:     SIGSEGV,
                    255: #ifdef SIGSYS
                    256:     SIGSYS,
                    257: #endif
                    258: #ifdef SIGXCPU
                    259:     SIGXCPU,
                    260: #endif
                    261: #ifdef SIGXFSZ
                    262:     SIGXFSZ,
                    263: #endif
                    264:   };
                    265:   static const int exit_signals[] = {
                    266:     SIGHUP,
                    267:     SIGINT,
                    268:     SIGALRM,
                    269:     SIGTERM,
                    270:     SIGUSR1,
                    271:     SIGUSR2,
                    272: #ifdef SIGPOLL
                    273:     SIGPOLL, 
                    274: #endif
                    275: #ifdef SIGVTALRM
                    276:     SIGVTALRM,
                    277: #endif
                    278: #ifdef SIGSTKFLT
                    279:     SIGSTKFLT, 
                    280: #endif
                    281:   };
                    282:   static const int ignore_signals[] = {
                    283:     SIGPIPE,
                    284:   };
                    285:   static const struct {
                    286:     const int *sigs;
                    287:     u_int nsigs;
                    288:     void (*handler)(int signo
                    289: #ifdef SA_SIGINFO
                    290:                    , siginfo_t *info, void *context
                    291: #endif
                    292:                   );
                    293:   } sigmap[] = {
1.1.1.2   misho     294:     { core_signals, array_size(core_signals), core_handler},
                    295:     { exit_signals, array_size(exit_signals), exit_handler},
                    296:     { ignore_signals, array_size(ignore_signals), NULL},
1.1       misho     297:   };
                    298:   u_int i;
                    299: 
1.1.1.2   misho     300:   for (i = 0; i < array_size(sigmap); i++)
1.1       misho     301:     {
                    302:       u_int j;
                    303: 
                    304:       for (j = 0; j < sigmap[i].nsigs; j++)
                    305:         {
                    306:          struct sigaction oact;
                    307:          if ((sigaction(sigmap[i].sigs[j],NULL,&oact) == 0) &&
                    308:              (oact.sa_handler == SIG_DFL))
                    309:            {
                    310:              struct sigaction act;
                    311:              sigfillset (&act.sa_mask);
                    312:              if (sigmap[i].handler == NULL)
                    313:                {
                    314:                  act.sa_handler = SIG_IGN;
                    315:                  act.sa_flags = 0;
                    316:                }
                    317:              else
                    318:                {
                    319: #ifdef SA_SIGINFO
                    320:                  /* Request extra arguments to signal handler. */
                    321:                  act.sa_sigaction = sigmap[i].handler;
                    322:                  act.sa_flags = SA_SIGINFO;
                    323: #else
                    324:                  act.sa_handler = sigmap[i].handler;
                    325:                  act.sa_flags = 0;
                    326: #endif
                    327:                }
                    328:              if (sigaction(sigmap[i].sigs[j],&act,NULL) < 0)
                    329:                zlog_warn("Unable to set signal handler for signal %d: %s",
                    330:                          sigmap[i].sigs[j],safe_strerror(errno));
                    331: 
                    332:            }
                    333:         }
                    334:     }
                    335: }
                    336: 
                    337: void 
                    338: signal_init (struct thread_master *m, int sigc, 
                    339:              struct quagga_signal_t signals[])
                    340: {
                    341: 
                    342:   int i = 0;
                    343:   struct quagga_signal_t *sig;
                    344: 
                    345:   /* First establish some default handlers that can be overridden by
                    346:      the application. */
                    347:   trap_default_signals();
                    348:   
                    349:   while (i < sigc)
                    350:     {
                    351:       sig = &signals[i];
                    352:       if ( signal_set (sig->signal) < 0 )
                    353:         exit (-1);
                    354:       i++;
                    355:     }
                    356: 
                    357:   sigmaster.sigc = sigc;
                    358:   sigmaster.signals = signals;
                    359: 
                    360: #ifdef SIGEVENT_SCHEDULE_THREAD  
                    361:   sigmaster.t = 
                    362:     thread_add_timer (m, quagga_signal_timer, &sigmaster, 
                    363:                       QUAGGA_SIGNAL_TIMER_INTERVAL);
                    364: #endif /* SIGEVENT_SCHEDULE_THREAD */
                    365: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>