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>