~james-page/ubuntu/saucy/openvswitch/1.12-snapshot

« back to all changes in this revision

Viewing changes to lib/signals.c

  • Committer: James Page
  • Date: 2013-08-21 10:16:57 UTC
  • mfrom: (1.1.20)
  • Revision ID: james.page@canonical.com-20130821101657-3o0z0qeiv5zkwlzi
New upstream snapshot

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (c) 2008, 2009, 2011, 2012 Nicira, Inc.
 
2
 * Copyright (c) 2008, 2009, 2011, 2012, 2013 Nicira, Inc.
3
3
 *
4
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
5
 * you may not use this file except in compliance with the License.
40
40
#endif
41
41
 
42
42
struct signal {
43
 
    struct sigaction saved_sa;
44
 
    int signr;
 
43
    int fds[2];
45
44
};
46
45
 
47
 
static volatile sig_atomic_t signaled[N_SIGNALS];
48
 
 
49
 
static int fds[2];
 
46
static struct signal signals[N_SIGNALS];
50
47
 
51
48
static void signal_handler(int signr);
52
49
 
53
 
/* Initializes the signals subsystem (if it is not already initialized).  Calls
54
 
 * exit() if initialization fails.
55
 
 *
56
 
 * Calling this function is optional; it will be called automatically by
57
 
 * signal_start() if necessary.  Calling it explicitly allows the client to
58
 
 * prevent the process from exiting at an unexpected time. */
59
 
void
60
 
signal_init(void)
61
 
{
62
 
    static bool inited;
63
 
    if (!inited) {
64
 
        inited = true;
65
 
        xpipe_nonblocking(fds);
66
 
    }
67
 
}
68
 
 
69
50
/* Sets up a handler for 'signr' and returns a structure that represents it.
70
51
 *
71
 
 * Only one handler for a given signal may be registered at a time. */
 
52
 * Only one handler for a given signal may be registered. */
72
53
struct signal *
73
54
signal_register(int signr)
74
55
{
75
56
    struct sigaction sa;
76
57
    struct signal *s;
77
58
 
78
 
    signal_init();
79
 
 
80
 
    s = xmalloc(sizeof *s);
81
 
    s->signr = signr;
82
 
 
83
 
    /* Set up signal handler. */
84
59
    ovs_assert(signr >= 1 && signr < N_SIGNALS);
 
60
 
 
61
    /* Create a pipe. */
 
62
    s = &signals[signr];
 
63
    ovs_assert(!s->fds[0] && !s->fds[1]);
 
64
    xpipe_nonblocking(s->fds);
 
65
 
 
66
    /* Install signal handler. */
85
67
    memset(&sa, 0, sizeof sa);
86
68
    sa.sa_handler = signal_handler;
87
69
    sigemptyset(&sa.sa_mask);
88
70
    sa.sa_flags = SA_RESTART;
89
 
    xsigaction(signr, &sa, &s->saved_sa);
 
71
    xsigaction(signr, &sa, NULL);
90
72
 
91
73
    return s;
92
74
}
93
75
 
94
 
/* Unregisters the handler for 's', restores the signal handler that was in
95
 
 * effect before signal_register() was called, and frees 's'. */
96
 
void
97
 
signal_unregister(struct signal *s)
98
 
{
99
 
    if (s) {
100
 
        xsigaction(s->signr, &s->saved_sa, NULL);
101
 
        free(s);
102
 
    }
103
 
}
104
 
 
105
76
/* Returns true if signal 's' has been received since the last call to this
106
77
 * function with argument 's'. */
107
78
bool
108
79
signal_poll(struct signal *s)
109
80
{
110
81
    char buf[_POSIX_PIPE_BUF];
111
 
    ignore(read(fds[0], buf, sizeof buf));
112
 
    if (signaled[s->signr]) {
113
 
        signaled[s->signr] = 0;
114
 
        return true;
115
 
    }
116
 
    return false;
 
82
 
 
83
    return read(s->fds[0], buf, sizeof buf) > 0;
117
84
}
118
85
 
119
86
/* Causes the next call to poll_block() to wake up when signal_poll(s) would
121
88
void
122
89
signal_wait(struct signal *s)
123
90
{
124
 
    if (signaled[s->signr]) {
125
 
        poll_immediate_wake();
126
 
    } else {
127
 
        poll_fd_wait(fds[0], POLLIN);
128
 
    }
 
91
    poll_fd_wait(s->fds[0], POLLIN);
129
92
}
130
93
 
131
94
static void
132
95
signal_handler(int signr)
133
96
{
134
97
    if (signr >= 1 && signr < N_SIGNALS) {
135
 
        ignore(write(fds[1], "", 1));
136
 
        signaled[signr] = true;
 
98
        ignore(write(signals[signr].fds[1], "", 1));
137
99
    }
138
100
}
139
101
 
140
 
/* Returns the name of signal 'signum' as a string.  The string may be in a
141
 
 * static buffer that is reused from one call to the next.
 
102
/* Returns the name of signal 'signum' as a string.  The return value is either
 
103
 * a statically allocated constant string or the 'bufsize'-byte buffer
 
104
 * 'namebuf'.  'bufsize' should be at least SIGNAL_NAME_BUFSIZE.
142
105
 *
143
106
 * The string is probably a (possibly multi-word) description of the signal
144
107
 * (e.g. "Hangup") instead of just the stringified version of the macro
145
108
 * (e.g. "SIGHUP"). */
146
109
const char *
147
 
signal_name(int signum)
 
110
signal_name(int signum, char *namebuf, size_t bufsize)
148
111
{
149
 
    const char *name = NULL;
150
 
#ifdef HAVE_STRSIGNAL
151
 
    name = strsignal(signum);
 
112
#if HAVE_DECL_SYS_SIGLIST
 
113
    if (signum >= 0 && signum < ARRAY_SIZE(sys_siglist)) {
 
114
        const char *name = sys_siglist[signum];
 
115
        if (name) {
 
116
            return name;
 
117
        }
 
118
    }
152
119
#endif
153
 
    if (!name) {
154
 
        static char buffer[7 + INT_STRLEN(int) + 1];
155
 
        sprintf(buffer, "signal %d", signum);
156
 
        name = buffer;
157
 
    }
158
 
    return name;
 
120
 
 
121
    snprintf(namebuf, bufsize, "signal %d", signum);
 
122
    return namebuf;
159
123
}
160
124
 
161
125
void
162
126
xsigaction(int signum, const struct sigaction *new, struct sigaction *old)
163
127
{
164
128
    if (sigaction(signum, new, old)) {
 
129
        char namebuf[SIGNAL_NAME_BUFSIZE];
 
130
 
165
131
        VLOG_FATAL("sigaction(%s) failed (%s)",
166
 
                   signal_name(signum), strerror(errno));
 
132
                   signal_name(signum, namebuf, sizeof namebuf),
 
133
                   ovs_strerror(errno));
167
134
    }
168
135
}
169
136
 
170
137
void
171
 
xsigprocmask(int how, const sigset_t *new, sigset_t *old)
 
138
xpthread_sigmask(int how, const sigset_t *new, sigset_t *old)
172
139
{
173
 
    if (sigprocmask(how, new, old)) {
174
 
        VLOG_FATAL("sigprocmask failed (%s)", strerror(errno));
 
140
    int error = pthread_sigmask(how, new, old);
 
141
    if (error) {
 
142
        VLOG_FATAL("pthread_sigmask failed (%s)", ovs_strerror(error));
175
143
    }
176
144
}