Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * pqsignal.c
4 : * Backend signal(2) support (see also src/port/pqsignal.c)
5 : *
6 : * Portions Copyright (c) 1996-2021, 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
41 2440 : pqinitmask(void)
42 : {
43 2440 : sigemptyset(&UnBlockSig);
44 :
45 : /* First set all signals, then clear some. */
46 2440 : sigfillset(&BlockSig);
47 2440 : 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 2440 : sigdelset(&BlockSig, SIGTRAP);
56 2440 : sigdelset(&StartupBlockSig, SIGTRAP);
57 : #endif
58 : #ifdef SIGABRT
59 2440 : sigdelset(&BlockSig, SIGABRT);
60 2440 : sigdelset(&StartupBlockSig, SIGABRT);
61 : #endif
62 : #ifdef SIGILL
63 2440 : sigdelset(&BlockSig, SIGILL);
64 2440 : sigdelset(&StartupBlockSig, SIGILL);
65 : #endif
66 : #ifdef SIGFPE
67 2440 : sigdelset(&BlockSig, SIGFPE);
68 2440 : sigdelset(&StartupBlockSig, SIGFPE);
69 : #endif
70 : #ifdef SIGSEGV
71 2440 : sigdelset(&BlockSig, SIGSEGV);
72 2440 : sigdelset(&StartupBlockSig, SIGSEGV);
73 : #endif
74 : #ifdef SIGBUS
75 2440 : sigdelset(&BlockSig, SIGBUS);
76 2440 : sigdelset(&StartupBlockSig, SIGBUS);
77 : #endif
78 : #ifdef SIGSYS
79 2440 : sigdelset(&BlockSig, SIGSYS);
80 2440 : sigdelset(&StartupBlockSig, SIGSYS);
81 : #endif
82 : #ifdef SIGCONT
83 2440 : sigdelset(&BlockSig, SIGCONT);
84 2440 : sigdelset(&StartupBlockSig, SIGCONT);
85 : #endif
86 :
87 : /* Signals unique to startup */
88 : #ifdef SIGQUIT
89 2440 : sigdelset(&StartupBlockSig, SIGQUIT);
90 : #endif
91 : #ifdef SIGTERM
92 2440 : sigdelset(&StartupBlockSig, SIGTERM);
93 : #endif
94 : #ifdef SIGALRM
95 2440 : sigdelset(&StartupBlockSig, SIGALRM);
96 : #endif
97 2440 : }
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
118 9624 : pqsignal_pm(int signo, pqsigfunc func)
119 : {
120 : #ifndef WIN32
121 : struct sigaction act,
122 : oact;
123 :
124 9624 : act.sa_handler = func;
125 9624 : if (func == SIG_IGN || func == SIG_DFL)
126 : {
127 : /* in these cases, act the same as pqsignal() */
128 4010 : sigemptyset(&act.sa_mask);
129 4010 : act.sa_flags = SA_RESTART;
130 : }
131 : else
132 : {
133 5614 : act.sa_mask = BlockSig;
134 5614 : act.sa_flags = 0;
135 : }
136 : #ifdef SA_NOCLDSTOP
137 9624 : if (signo == SIGCHLD)
138 802 : act.sa_flags |= SA_NOCLDSTOP;
139 : #endif
140 9624 : if (sigaction(signo, &act, &oact) < 0)
141 0 : return SIG_ERR;
142 9624 : return oact.sa_handler;
143 : #else /* WIN32 */
144 : return pqsignal(signo, func);
145 : #endif
146 : }
|