~ubuntu-branches/ubuntu/utopic/haproxy/utopic-proposed

« back to all changes in this revision

Viewing changes to src/signal.c

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Cornet
  • Date: 2009-06-26 00:11:01 UTC
  • mfrom: (1.1.6 upstream) (2.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090626001101-qo261ke2mjh3d8cn
* New Upstream Version (Closes: #534583).
* Add contrib directory in docs

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Asynchronous signal delivery functions.
 
3
 *
 
4
 * Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version
 
9
 * 2 of the License, or (at your option) any later version.
 
10
 *
 
11
 */
 
12
 
 
13
#include <signal.h>
 
14
#include <proto/signal.h>
 
15
#include <proto/log.h>
 
16
 
 
17
/* Principle : we keep an in-order list of the first occurrence of all received
 
18
 * signals. All occurrences of a same signal are grouped though. The signal
 
19
 * queue does not need to be deeper than the number of signals we can handle.
 
20
 * The handlers will be called asynchronously with the signal number. They can
 
21
 * check themselves the number of calls by checking the descriptor this signal.
 
22
 */
 
23
 
 
24
int signal_queue_len; /* length of signal queue, <= MAX_SIGNAL (1 entry per signal max) */
 
25
int signal_queue[MAX_SIGNAL];                     /* in-order queue of received signals */
 
26
struct signal_descriptor signal_state[MAX_SIGNAL];
 
27
sigset_t blocked_sig;
 
28
 
 
29
void signal_init()
 
30
{
 
31
        signal_queue_len = 0;
 
32
        memset(signal_queue, 0, sizeof(signal_queue));
 
33
        memset(signal_state, 0, sizeof(signal_state));
 
34
        sigfillset(&blocked_sig);
 
35
}
 
36
 
 
37
void signal_handler(int sig)
 
38
{
 
39
        if (sig < 0 || sig > MAX_SIGNAL || !signal_state[sig].handler) {
 
40
                /* unhandled signal */
 
41
                qfprintf(stderr, "Received unhandled signal %d. Signal has been disabled.\n", sig);
 
42
                signal(sig, SIG_IGN);
 
43
                return;
 
44
        }
 
45
 
 
46
        if (!signal_state[sig].count) {
 
47
                /* signal was not queued yet */
 
48
                if (signal_queue_len < MAX_SIGNAL)
 
49
                        signal_queue[signal_queue_len++] = sig;
 
50
                else
 
51
                        qfprintf(stderr, "Signal %d : signal queue is unexpectedly full.\n", sig);
 
52
        }
 
53
        signal_state[sig].count++;
 
54
        signal(sig, signal_handler); /* re-arm signal */
 
55
}
 
56
 
 
57
/* Register a handler for signal <sig>. Set it to NULL, SIG_DFL or SIG_IGN to
 
58
 * remove the handler. The signal's queue is flushed and the signal is really
 
59
 * registered (or unregistered) for the process. The interface is the same as
 
60
 * for standard signal delivery, except that the handler does not need to rearm
 
61
 * the signal itself (it can disable it however).
 
62
 */
 
63
void signal_register(int sig, void (*handler)(int))
 
64
{
 
65
        if (sig < 0 || sig > MAX_SIGNAL) {
 
66
                qfprintf(stderr, "Failed to register signal %d : out of range [0..%d].\n", sig, MAX_SIGNAL);
 
67
                return;
 
68
        }
 
69
 
 
70
        signal_state[sig].count = 0;
 
71
        if (handler == NULL)
 
72
                handler = SIG_IGN;
 
73
 
 
74
        if (handler != SIG_IGN && handler != SIG_DFL) {
 
75
                signal_state[sig].handler = handler;
 
76
                signal(sig, signal_handler);
 
77
        }
 
78
        else {
 
79
                signal_state[sig].handler = NULL;
 
80
                signal(sig, handler);
 
81
        }
 
82
}
 
83
 
 
84
/* Call handlers of all pending signals and clear counts and queue length. The
 
85
 * handlers may unregister themselves by calling signal_register() while they
 
86
 * are called, just like it is done with normal signal handlers.
 
87
 * Note that it is more efficient to call the inline version which checks the
 
88
 * queue length before getting here.
 
89
 */
 
90
void __signal_process_queue()
 
91
{
 
92
        int sig, cur_pos = 0;
 
93
        struct signal_descriptor *desc;
 
94
        sigset_t old_sig;
 
95
 
 
96
        /* block signal delivery during processing */
 
97
        sigprocmask(SIG_SETMASK, &blocked_sig, &old_sig);
 
98
 
 
99
        for (cur_pos = 0; cur_pos < signal_queue_len; cur_pos++) {
 
100
                sig  = signal_queue[cur_pos];
 
101
                desc = &signal_state[sig];
 
102
                if (desc->count) {
 
103
                        if (desc->handler)
 
104
                                desc->handler(sig);
 
105
                        desc->count = 0;
 
106
                }
 
107
        }
 
108
        signal_queue_len = 0;
 
109
 
 
110
        /* restore signal delivery */
 
111
        sigprocmask(SIG_SETMASK, &old_sig, NULL);
 
112
}