1 /*-------------------------------------------------------------------------
2 *
3 * pqsignal.c
4 * Backend signal(2) support (see also src/port/pqsignal.c)
5 *
6 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/libpq/pqsignal.c
12 *
13 * ------------------------------------------------------------------------
14 */
15
16 #include "postgres.h"
17
18 #include "libpq/pqsignal.h"
19
20
21 /* Global variables */
22 sigset_t UnBlockSig,
23 BlockSig,
24 StartupBlockSig;
25
26
27 /*
28 * Initialize BlockSig, UnBlockSig, and StartupBlockSig.
29 *
30 * BlockSig is the set of signals to block when we are trying to block
31 * signals. This includes all signals we normally expect to get, but NOT
32 * signals that should never be turned off.
33 *
34 * StartupBlockSig is the set of signals to block during startup packet
35 * collection; it's essentially BlockSig minus SIGTERM, SIGQUIT, SIGALRM.
36 *
37 * UnBlockSig is the set of signals to block when we don't want to block
38 * signals (is this ever nonzero??)
39 */
40 void
pqinitmask(void)41 pqinitmask(void)
42 {
43 sigemptyset(&UnBlockSig);
44
45 /* First set all signals, then clear some. */
46 sigfillset(&BlockSig);
47 sigfillset(&StartupBlockSig);
48
49 /*
50 * Unmark those signals that should never be blocked. Some of these signal
51 * names don't exist on all platforms. Most do, but might as well ifdef
52 * them all for consistency...
53 */
54 #ifdef SIGTRAP
55 sigdelset(&BlockSig, SIGTRAP);
56 sigdelset(&StartupBlockSig, SIGTRAP);
57 #endif
58 #ifdef SIGABRT
59 sigdelset(&BlockSig, SIGABRT);
60 sigdelset(&StartupBlockSig, SIGABRT);
61 #endif
62 #ifdef SIGILL
63 sigdelset(&BlockSig, SIGILL);
64 sigdelset(&StartupBlockSig, SIGILL);
65 #endif
66 #ifdef SIGFPE
67 sigdelset(&BlockSig, SIGFPE);
68 sigdelset(&StartupBlockSig, SIGFPE);
69 #endif
70 #ifdef SIGSEGV
71 sigdelset(&BlockSig, SIGSEGV);
72 sigdelset(&StartupBlockSig, SIGSEGV);
73 #endif
74 #ifdef SIGBUS
75 sigdelset(&BlockSig, SIGBUS);
76 sigdelset(&StartupBlockSig, SIGBUS);
77 #endif
78 #ifdef SIGSYS
79 sigdelset(&BlockSig, SIGSYS);
80 sigdelset(&StartupBlockSig, SIGSYS);
81 #endif
82 #ifdef SIGCONT
83 sigdelset(&BlockSig, SIGCONT);
84 sigdelset(&StartupBlockSig, SIGCONT);
85 #endif
86
87 /* Signals unique to startup */
88 #ifdef SIGQUIT
89 sigdelset(&StartupBlockSig, SIGQUIT);
90 #endif
91 #ifdef SIGTERM
92 sigdelset(&StartupBlockSig, SIGTERM);
93 #endif
94 #ifdef SIGALRM
95 sigdelset(&StartupBlockSig, SIGALRM);
96 #endif
97 }
98
99 /*
100 * Set up a postmaster signal handler for signal "signo"
101 *
102 * Returns the previous handler.
103 *
104 * This is used only in the postmaster, which has its own odd approach to
105 * signal handling. For signals with handlers, we block all signals for the
106 * duration of signal handler execution. We also do not set the SA_RESTART
107 * flag; this should be safe given the tiny range of code in which the
108 * postmaster ever unblocks signals.
109 *
110 * pqinitmask() must have been invoked previously.
111 *
112 * On Windows, this function is just an alias for pqsignal()
113 * (and note that it's calling the code in src/backend/port/win32/signal.c,
114 * not src/port/pqsignal.c). On that platform, the postmaster's signal
115 * handlers still have to block signals for themselves.
116 */
117 pqsigfunc
pqsignal_pm(int signo,pqsigfunc func)118 pqsignal_pm(int signo, pqsigfunc func)
119 {
120 #ifndef WIN32
121 struct sigaction act,
122 oact;
123
124 act.sa_handler = func;
125 if (func == SIG_IGN || func == SIG_DFL)
126 {
127 /* in these cases, act the same as pqsignal() */
128 sigemptyset(&act.sa_mask);
129 act.sa_flags = SA_RESTART;
130 }
131 else
132 {
133 act.sa_mask = BlockSig;
134 act.sa_flags = 0;
135 }
136 #ifdef SA_NOCLDSTOP
137 if (signo == SIGCHLD)
138 act.sa_flags |= SA_NOCLDSTOP;
139 #endif
140 if (sigaction(signo, &act, &oact) < 0)
141 return SIG_ERR;
142 return oact.sa_handler;
143 #else /* WIN32 */
144 return pqsignal(signo, func);
145 #endif
146 }
147