~ubuntu-branches/ubuntu/hoary/postfix/hoary-security

« back to all changes in this revision

Viewing changes to src/master/master_sig.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-10-06 11:50:33 UTC
  • Revision ID: james.westby@ubuntu.com-20041006115033-ooo6yfg6kmoteu04
Tags: upstream-2.1.3
ImportĀ upstreamĀ versionĀ 2.1.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*++
 
2
/* NAME
 
3
/*      master_sig 3
 
4
/* SUMMARY
 
5
/*      Postfix master - signal processing
 
6
/* SYNOPSIS
 
7
/*      #include "master.h"
 
8
/*
 
9
/*      int     master_gotsighup;
 
10
/*      int     master_gotsigchld;
 
11
/*
 
12
/*      int     master_sigsetup()
 
13
/* DESCRIPTION
 
14
/*      This module implements the master process signal handling interface.
 
15
/*
 
16
/*      master_gotsighup (master_gotsigchld) is set to SIGHUP (SIGCHLD)
 
17
/*      when the process receives a hangup (child death) signal.
 
18
/*
 
19
/*      master_sigsetup() enables processing of hangup and child death signals.
 
20
/*      Receipt of SIGINT, SIGQUIT, SIGSEGV, SIGILL, or SIGTERM
 
21
/*      is interpreted as a request for termination.  Child processes are
 
22
/*      notified of the master\'s demise by sending them a SIGTERM signal.
 
23
/* DIAGNOSTICS
 
24
/* BUGS
 
25
/*      Need a way to register cleanup actions.
 
26
/* SEE ALSO
 
27
/* LICENSE
 
28
/* .ad
 
29
/* .fi
 
30
/*      The Secure Mailer license must be distributed with this software.
 
31
/* AUTHOR(S)
 
32
/*      Wietse Venema
 
33
/*      IBM T.J. Watson Research
 
34
/*      P.O. Box 704
 
35
/*      Yorktown Heights, NY 10598, USA
 
36
/*--*/
 
37
 
 
38
/* System libraries. */
 
39
 
 
40
#include <sys_defs.h>
 
41
#include <signal.h>
 
42
#include <unistd.h>
 
43
 
 
44
/* Utility library. */
 
45
 
 
46
#include <msg.h>
 
47
#include <posix_signals.h>
 
48
 
 
49
/* Application-specific. */
 
50
 
 
51
#include "master.h"
 
52
 
 
53
#ifdef USE_SIG_RETURN
 
54
#include <sys/syscall.h>
 
55
#endif
 
56
 
 
57
#ifndef USE_SIG_RETURN
 
58
#define USE_SIG_PIPE
 
59
#endif
 
60
 
 
61
/* Local stuff. */
 
62
 
 
63
#ifdef USE_SIG_PIPE
 
64
#include <errno.h>
 
65
#include <fcntl.h>
 
66
#include <iostuff.h>
 
67
#include <events.h>
 
68
 
 
69
int     master_sig_pipe[2];
 
70
 
 
71
#define SIG_PIPE_WRITE_FD master_sig_pipe[1]
 
72
#define SIG_PIPE_READ_FD master_sig_pipe[0]
 
73
#endif
 
74
 
 
75
int     master_gotsigchld;
 
76
int     master_gotsighup;
 
77
 
 
78
/* master_sighup - register arrival of hangup signal */
 
79
 
 
80
static void master_sighup(int sig)
 
81
{
 
82
 
 
83
    /*
 
84
     * WARNING WARNING WARNING.
 
85
     * 
 
86
     * This code runs at unpredictable moments, as a signal handler. Don't put
 
87
     * any code here other than for setting a global flag.
 
88
     */
 
89
    master_gotsighup = sig;
 
90
}
 
91
 
 
92
/* master_sigchld - register arrival of child death signal */
 
93
 
 
94
#ifdef USE_SIG_RETURN
 
95
 
 
96
static void master_sigchld(int sig, int code, struct sigcontext * scp)
 
97
{
 
98
 
 
99
    /*
 
100
     * WARNING WARNING WARNING.
 
101
     * 
 
102
     * This code runs at unpredictable moments, as a signal handler. Don't put
 
103
     * any code here other than for setting a global flag, or code that is
 
104
     * intended to be run within a signal handler.
 
105
     */
 
106
    master_gotsigchld = sig;
 
107
    if (scp != NULL && scp->sc_syscall == SYS_select) {
 
108
        scp->sc_syscall_action = SIG_RETURN;
 
109
#ifndef SA_RESTART
 
110
    } else if (scp != NULL) {
 
111
        scp->sc_syscall_action = SIG_RESTART;
 
112
#endif
 
113
    }
 
114
}
 
115
 
 
116
#else
 
117
 
 
118
#ifdef USE_SIG_PIPE
 
119
 
 
120
/* master_sigchld - force wakeup from select() */
 
121
 
 
122
static void master_sigchld(int unused_sig)
 
123
{
 
124
    int     saved_errno = errno;
 
125
 
 
126
    /*
 
127
     * WARNING WARNING WARNING.
 
128
     * 
 
129
     * This code runs at unpredictable moments, as a signal handler. Don't put
 
130
     * any code here other than for setting a global flag, or code that is
 
131
     * intended to be run within a signal handler. Restore errno in case we
 
132
     * are interrupting the epilog of a failed system call.
 
133
     */
 
134
    if (write(SIG_PIPE_WRITE_FD, "", 1) != 1)
 
135
        msg_warn("write to SIG_PIPE_WRITE_FD failed: %m");
 
136
    errno = saved_errno;
 
137
}
 
138
 
 
139
/* master_sig_event - called upon return from select() */
 
140
 
 
141
static void master_sig_event(int unused_event, char *unused_context)
 
142
{
 
143
    char    c[1];
 
144
 
 
145
    while (read(SIG_PIPE_READ_FD, c, 1) > 0)
 
146
         /* void */ ;
 
147
    master_gotsigchld = 1;
 
148
}
 
149
 
 
150
#else
 
151
 
 
152
static void master_sigchld(int sig)
 
153
{
 
154
 
 
155
    /*
 
156
     * WARNING WARNING WARNING.
 
157
     * 
 
158
     * This code runs at unpredictable moments, as a signal handler. Don't put
 
159
     * any code here other than for setting a global flag.
 
160
     */
 
161
    master_gotsigchld = sig;
 
162
}
 
163
 
 
164
#endif
 
165
#endif
 
166
 
 
167
/* master_sigdeath - die, women and children first */
 
168
 
 
169
static void master_sigdeath(int sig)
 
170
{
 
171
    char   *myname = "master_sigdeath";
 
172
    struct sigaction action;
 
173
    pid_t   pid = getpid();
 
174
 
 
175
    /*
 
176
     * XXX We're running from a signal handler, and really should not call
 
177
     * any msg() routines at all, but it would be even worse to silently
 
178
     * terminate without informing the sysadmin.
 
179
     */
 
180
    msg_info("terminating on signal %d", sig);
 
181
 
 
182
    /*
 
183
     * Terminate all processes in our process group, except ourselves.
 
184
     */
 
185
    sigemptyset(&action.sa_mask);
 
186
    action.sa_flags = 0;
 
187
    action.sa_handler = SIG_IGN;
 
188
    if (sigaction(SIGTERM, &action, (struct sigaction *) 0) < 0)
 
189
        msg_fatal("%s: sigaction: %m", myname);
 
190
    if (kill(-pid, SIGTERM) < 0)
 
191
        msg_fatal("%s: kill process group: %m", myname);
 
192
 
 
193
    /*
 
194
     * Deliver the signal to ourselves and clean up. XXX We're running as a
 
195
     * signal handler and really should not be doing complicated things...
 
196
     */
 
197
    sigemptyset(&action.sa_mask);
 
198
    action.sa_flags = 0;
 
199
    action.sa_handler = SIG_DFL;
 
200
    if (sigaction(sig, &action, (struct sigaction *) 0) < 0)
 
201
        msg_fatal("%s: sigaction: %m", myname);
 
202
    if (kill(pid, sig) < 0)
 
203
        msg_fatal("%s: kill myself: %m", myname);
 
204
}
 
205
 
 
206
/* master_sigsetup - set up signal handlers */
 
207
 
 
208
void    master_sigsetup(void)
 
209
{
 
210
    char   *myname = "master_sigsetup";
 
211
    struct sigaction action;
 
212
    static int sigs[] = {
 
213
        SIGINT, SIGQUIT, SIGILL, SIGBUS, SIGSEGV, SIGTERM,
 
214
    };
 
215
    unsigned i;
 
216
 
 
217
    sigemptyset(&action.sa_mask);
 
218
    action.sa_flags = 0;
 
219
 
 
220
    /*
 
221
     * Prepare to kill our children when we receive any of the above signals.
 
222
     */
 
223
    action.sa_handler = master_sigdeath;
 
224
    for (i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++)
 
225
        if (sigaction(sigs[i], &action, (struct sigaction *) 0) < 0)
 
226
            msg_fatal("%s: sigaction(%d): %m", myname, sigs[i]);
 
227
 
 
228
#ifdef USE_SIG_PIPE
 
229
    if (pipe(master_sig_pipe))
 
230
        msg_fatal("pipe: %m");
 
231
    non_blocking(SIG_PIPE_WRITE_FD, NON_BLOCKING);
 
232
    non_blocking(SIG_PIPE_READ_FD, NON_BLOCKING);
 
233
    close_on_exec(SIG_PIPE_WRITE_FD, CLOSE_ON_EXEC);
 
234
    close_on_exec(SIG_PIPE_READ_FD, CLOSE_ON_EXEC);
 
235
    event_enable_read(SIG_PIPE_READ_FD, master_sig_event, (char *) 0);
 
236
#endif
 
237
 
 
238
    /*
 
239
     * Intercept SIGHUP (re-read config file) and SIGCHLD (child exit).
 
240
     */
 
241
#ifdef SA_RESTART
 
242
    action.sa_flags |= SA_RESTART;
 
243
#endif
 
244
    action.sa_handler = master_sighup;
 
245
    if (sigaction(SIGHUP, &action, (struct sigaction *) 0) < 0)
 
246
        msg_fatal("%s: sigaction(%d): %m", myname, SIGHUP);
 
247
 
 
248
    action.sa_flags |= SA_NOCLDSTOP;
 
249
    action.sa_handler = master_sigchld;
 
250
    if (sigaction(SIGCHLD, &action, (struct sigaction *) 0) < 0)
 
251
        msg_fatal("%s: sigaction(%d): %m", myname, SIGCHLD);
 
252
}