PostgreSQL Source Code
git master
Loading...
Searching...
No Matches
pqsignal.c
Go to the documentation of this file.
1
/*-------------------------------------------------------------------------
2
*
3
* pqsignal.c
4
* reliable BSD-style signal(2) routine stolen from RWW who stole it
5
* from Stevens...
6
*
7
* Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
8
* Portions Copyright (c) 1994, Regents of the University of California
9
*
10
*
11
* IDENTIFICATION
12
* src/port/pqsignal.c
13
*
14
* This is the signal() implementation from "Advanced Programming in the UNIX
15
* Environment", with minor changes. It was originally a replacement needed
16
* for old SVR4 systems whose signal() behaved as if sa_flags = SA_RESETHAND |
17
* SA_NODEFER, also known as "unreliable" signals due to races when the
18
* handler was reset.
19
*
20
* By now, all known modern Unix systems have a "reliable" signal() call.
21
* We still don't want to use it though, because it remains
22
* implementation-defined by both C99 and POSIX whether the handler is reset
23
* or signals are blocked when the handler runs, and default restart behavior
24
* is also unspecified. Therefore we take POSIX's advice and call sigaction()
25
* so we can provide explicit sa_flags, but wrap it in this more convenient
26
* traditional interface style. It also provides a place to set any extra
27
* flags we want everywhere, such as SA_NOCLDSTOP.
28
*
29
* Windows, of course, is resolutely in a class by itself. In the backend,
30
* this relies on pqsigaction() in src/backend/port/win32/signal.c, which
31
* provides limited emulation of reliable signals.
32
*
33
* Frontend programs can use this version of pqsignal() to forward to the
34
* native Windows signal() call if they wish, but beware that Windows signals
35
* behave quite differently. Only the 6 signals required by C are supported.
36
* SIGINT handlers run in another thread instead of interrupting an existing
37
* thread, and the others don't interrupt system calls either, so SA_RESTART
38
* is moot. All except SIGFPE have SA_RESETHAND semantics, meaning the
39
* handler is reset to SIG_DFL each time it runs. The set of things you are
40
* allowed to do in a handler is also much more restricted than on Unix,
41
* according to the documentation.
42
*
43
* ------------------------------------------------------------------------
44
*/
45
46
#include "
c.h
"
47
48
#include <signal.h>
49
#ifndef FRONTEND
50
#include <
unistd.h
>
51
#endif
52
53
#ifndef FRONTEND
54
#include "
libpq/pqsignal.h
"
55
#include "
miscadmin.h
"
56
#endif
57
58
#ifdef PG_SIGNAL_COUNT
/* Windows */
59
#define PG_NSIG (PG_SIGNAL_COUNT)
60
#elif defined(NSIG)
61
#define PG_NSIG (NSIG)
62
#else
63
#define PG_NSIG (64)
/* XXX: wild guess */
64
#endif
65
66
#if !(defined(WIN32) && defined(FRONTEND))
67
#define USE_SIGACTION
68
#endif
69
70
#if defined(USE_SIGACTION) && defined(HAVE_SA_SIGINFO)
71
#define USE_SIGINFO
72
#endif
73
74
/* Check a couple of common signals to make sure PG_NSIG is accurate. */
75
StaticAssertDecl
(
SIGUSR2 < PG_NSIG, "SIGUSR2 >
=
PG_NSIG
");
76
StaticAssertDecl(SIGHUP < PG_NSIG, "
SIGHUP
>=
PG_NSIG
");
77
StaticAssertDecl(SIGTERM < PG_NSIG, "
SIGTERM
>=
PG_NSIG
");
78
StaticAssertDecl(SIGALRM < PG_NSIG, "
SIGALRM
>=
PG_NSIG
");
79
80
static volatile pqsigfunc pqsignal_handlers[PG_NSIG];
81
82
/*
83
* Except when called with SIG_IGN or SIG_DFL, pqsignal() sets up this function
84
* as the handler for all signals. This wrapper handler function checks that
85
* it is called within a process that knew to maintain MyProcPid, and not a
86
* child process forked by system(3), etc. This check ensures that such child
87
* processes do not modify shared memory, which is often detrimental. If the
88
* check succeeds, the function originally provided to pqsignal() is called.
89
* Otherwise, the default signal handler is installed and then called.
90
*
91
* This wrapper also handles restoring the value of errno.
92
*/
93
#if defined(USE_SIGACTION) && defined(USE_SIGINFO)
94
static void
95
wrapper_handler(int postgres_signal_arg, siginfo_t * info, void *context)
96
#else /* no USE_SIGINFO */
97
static void
98
wrapper_handler(int postgres_signal_arg)
99
#endif
100
{
101
int save_errno = errno;
102
pg_signal_info pg_info;
103
104
Assert(postgres_signal_arg > 0);
105
Assert(postgres_signal_arg < PG_NSIG);
106
107
#ifndef FRONTEND
108
109
/*
110
* We expect processes to set MyProcPid before calling pqsignal() or
111
* before accepting signals.
112
*/
113
Assert(MyProcPid);
114
Assert(MyProcPid != PostmasterPid || !IsUnderPostmaster);
115
116
if (unlikely(MyProcPid != (int) getpid()))
117
{
118
pqsignal(postgres_signal_arg, PG_SIG_DFL);
119
raise(postgres_signal_arg);
120
return;
121
}
122
#endif
123
124
#ifdef HAVE_SA_SIGINFO
125
126
/*
127
* If supported by the system, forward interesting information from the
128
* system's extended signal information to our platform independent
129
* format.
130
*/
131
pg_info.pid = info->si_pid;
132
pg_info.uid = info->si_uid;
133
#else
134
135
/*
136
* Otherwise forward values indicating that we do not have the
137
* information.
138
*/
139
pg_info.pid = 0;
140
pg_info.uid = 0;
141
#endif
142
143
(*pqsignal_handlers[postgres_signal_arg]) (postgres_signal_arg, &pg_info);
144
145
errno = save_errno;
146
}
147
148
/*
149
* Set up a signal handler, with SA_RESTART, for signal "
signo
"
150
*
151
* Note: the actual name of this function is either pqsignal_fe when
152
* compiled with -DFRONTEND, or pqsignal_be when compiled without that.
153
* This is to avoid a name collision with libpq's legacy-pqsignal.c.
154
*/
155
void
156
pqsignal(int signo, pqsigfunc func)
157
{
158
#ifdef USE_SIGACTION
159
struct sigaction act;
160
#else
161
void (*wrapper_func_ptr) (int);
162
#endif
163
bool is_ign = func == PG_SIG_IGN;
164
bool is_dfl = func == PG_SIG_DFL;
165
166
Assert(signo > 0);
167
Assert(signo < PG_NSIG);
168
169
/* set up indirection handler */
170
if (!(is_ign || is_dfl))
171
{
172
pqsignal_handlers[signo] = func; /* assumed atomic */
173
}
174
175
/*
176
* Configure system to either ignore/reset the signal handler, or to
177
* forward it to wrapper_handler.
178
*/
179
#ifdef USE_SIGACTION
180
sigemptyset(&act.sa_mask);
181
act.sa_flags = SA_RESTART;
182
183
if (is_ign)
184
act.sa_handler = SIG_IGN;
185
else if (is_dfl)
186
act.sa_handler = SIG_DFL;
187
#ifdef USE_SIGINFO
188
else
189
{
190
act.sa_sigaction = wrapper_handler;
191
act.sa_flags |= SA_SIGINFO;
192
}
193
#else
194
else
195
act.sa_handler = wrapper_handler;
196
#endif
197
198
#ifdef SA_NOCLDSTOP
199
if (signo == SIGCHLD)
200
act.sa_flags |= SA_NOCLDSTOP;
201
#endif
202
if (sigaction(signo, &act, NULL) < 0)
203
Assert(false); /* probably indicates coding error */
204
#else /* no USE_SIGACTION */
205
206
/*
207
* Forward to Windows native signal system, we need to send this though
208
* wrapper handler as it it needs to take single argument only.
209
*/
210
if (is_ign)
211
wrapper_func_ptr = SIG_IGN;
212
else if (is_dfl)
213
wrapper_func_ptr = SIG_DFL;
214
else
215
wrapper_func_ptr = wrapper_handler;
216
217
if (signal(signo, wrapper_func_ptr) == SIG_ERR)
218
Assert(false); /* probably indicates coding error */
219
#endif
220
}
c.h
miscadmin.h
PG_NSIG
#define PG_NSIG
Definition
pqsignal.c:63
StaticAssertDecl
StaticAssertDecl(SIGUSR2< PG_NSIG, "SIGUSR2 >= PG_NSIG")
pqsignal.h
fb
static int fb(int x)
Definition
preproc-init.c:92
unistd.h
SIGHUP
#define SIGHUP
Definition
win32_port.h:158
SIGALRM
#define SIGALRM
Definition
win32_port.h:164
src
port
pqsignal.c
Generated on Fri Apr 17 2026 22:13:17 for PostgreSQL Source Code by
1.9.8