Skip to content

Commit 3445b45

Browse files
author
Daniel Shelepanov
committed
[PGPRO-4561] Blocking custom signals while handling one
Without HOLD_INTERRUPTS()/RESUME_INTERRUPTS() there is a risk of accepting a signal while executing another signal handler which leads to a hcs memory context corruption. tags: pg_query_state
1 parent 2aeee15 commit 3445b45

File tree

3 files changed

+165
-65
lines changed

3 files changed

+165
-65
lines changed

patches/custom_signals_13.0.patch

Lines changed: 87 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c
2-
index 4fa385b0ece..fc1637a2e28 100644
2+
index 4fa385b0ece..60854eee386 100644
33
--- a/src/backend/storage/ipc/procsignal.c
44
+++ b/src/backend/storage/ipc/procsignal.c
55
@@ -88,12 +88,21 @@ typedef struct
6-
(((flags) & (((uint32) 1) << (uint32) (type))) != 0)
7-
6+
(((flags) & (((uint32) 1) << (uint32) (type))) != 0)
7+
88
static ProcSignalHeader *ProcSignal = NULL;
99
+#define IsCustomProcSignalReason(reason) \
1010
+ ((reason) >= PROCSIG_CUSTOM_1 && (reason) <= PROCSIG_CUSTOM_N)
@@ -14,20 +14,20 @@ index 4fa385b0ece..fc1637a2e28 100644
1414
+static ProcSignalHandler_type CustomInterruptHandlers[NUM_CUSTOM_PROCSIGNALS];
1515
+
1616
static volatile ProcSignalSlot *MyProcSignalSlot = NULL;
17-
17+
1818
static bool CheckProcSignal(ProcSignalReason reason);
1919
static void CleanupProcSignalState(int status, Datum arg);
2020
static void ProcessBarrierPlaceholder(void);
21-
21+
2222
+static void CheckAndSetCustomSignalInterrupts(void);
2323
+
2424
/*
2525
* ProcSignalShmemSize
2626
* Compute space needed for procsignal's shared memory
2727
@@ -235,6 +244,36 @@ CleanupProcSignalState(int status, Datum arg)
28-
slot->pss_pid = 0;
28+
slot->pss_pid = 0;
2929
}
30-
30+
3131
+/*
3232
+ * RegisterCustomProcSignalHandler
3333
+ * Assign specific handler of custom process signal with new
@@ -61,17 +61,17 @@ index 4fa385b0ece..fc1637a2e28 100644
6161
/*
6262
* SendProcSignal
6363
* Send a signal to a Postgres process
64-
@@ -585,9 +624,64 @@ procsignal_sigusr1_handler(SIGNAL_ARGS)
65-
if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN))
66-
RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN);
67-
64+
@@ -585,9 +624,71 @@ procsignal_sigusr1_handler(SIGNAL_ARGS)
65+
if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN))
66+
RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN);
67+
6868
+ CheckAndSetCustomSignalInterrupts();
6969
+
70-
SetLatch(MyLatch);
71-
72-
latch_sigusr1_handler();
73-
74-
errno = save_errno;
70+
SetLatch(MyLatch);
71+
72+
latch_sigusr1_handler();
73+
74+
errno = save_errno;
7575
}
7676
+
7777
+/*
@@ -108,9 +108,15 @@ index 4fa385b0ece..fc1637a2e28 100644
108108
+{
109109
+ int i;
110110
+
111-
+ /* Check on expiring of custom signals and call its handlers if exist */
111+
+ /*
112+
+ * This is invoked from ProcessInterrupts(), and since some of the
113+
+ * functions it calls contain CHECK_FOR_INTERRUPTS(), there is a potential
114+
+ * for recursive calls if more signals are received while this runs, so
115+
+ * let's block interrupts until done.
116+
+ */
117+
+ HOLD_INTERRUPTS();
118+
+
112119
+ for (i = 0; i < NUM_CUSTOM_PROCSIGNALS; i++)
113-
+ {
114120
+ if (!CustomSignalProcessing[i] && CustomSignalPendings[i])
115121
+ {
116122
+ ProcSignalHandler_type handler;
@@ -124,29 +130,66 @@ index 4fa385b0ece..fc1637a2e28 100644
124130
+ CustomSignalProcessing[i] = false;
125131
+ }
126132
+ }
127-
+ }
133+
+
134+
+ RESUME_INTERRUPTS();
128135
+}
129136
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
130-
index 174c72a14bc..0e7366bd58f 100644
137+
index 7bc03ae4edc..3debd63bd7d 100644
131138
--- a/src/backend/tcop/postgres.c
132139
+++ b/src/backend/tcop/postgres.c
133-
@@ -3221,6 +3221,8 @@ ProcessInterrupts(void)
134-
135-
if (ParallelMessagePending)
136-
HandleParallelMessages();
140+
@@ -5,6 +5,7 @@
141+
*
142+
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
143+
* Portions Copyright (c) 1994, Regents of the University of California
144+
+ * Portions Copyright (c) 2020-2021, Postgres Professional
145+
*
146+
*
147+
* IDENTIFICATION
148+
@@ -74,6 +75,7 @@
149+
#include "tcop/pquery.h"
150+
#include "tcop/tcopprot.h"
151+
#include "tcop/utility.h"
152+
+#include "utils/builtins.h"
153+
#include "utils/lsyscache.h"
154+
#include "utils/memutils.h"
155+
#include "utils/ps_status.h"
156+
@@ -3231,6 +3233,8 @@ ProcessInterrupts(void)
157+
158+
if (ParallelMessagePending)
159+
HandleParallelMessages();
137160
+
138161
+ CheckAndHandleCustomSignals();
139162
}
140-
141-
163+
164+
165+
@@ -3576,7 +3580,7 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx,
166+
* postmaster/postmaster.c (the option sets should not conflict) and with
167+
* the common help() function in main/main.c.
168+
*/
169+
- while ((flag = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:-:")) != -1)
170+
+ while ((flag = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:Z-:")) != -1)
171+
{
172+
switch (flag)
173+
{
174+
@@ -3712,6 +3716,10 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx,
175+
SetConfigOption("post_auth_delay", optarg, ctx, gucsource);
176+
break;
177+
178+
+ case 'Z':
179+
+ /* ignored for consistency with the postmaster */
180+
+ break;
181+
+
182+
case 'c':
183+
case '-':
184+
{
142185
diff --git a/src/include/storage/procsignal.h b/src/include/storage/procsignal.h
143186
index 5cb39697f38..c05f60fa719 100644
144187
--- a/src/include/storage/procsignal.h
145188
+++ b/src/include/storage/procsignal.h
146189
@@ -17,6 +17,8 @@
147190
#include "storage/backendid.h"
148-
149-
191+
192+
150193
+#define NUM_CUSTOM_PROCSIGNALS 64
151194
+
152195
/*
@@ -158,13 +201,13 @@ index 5cb39697f38..c05f60fa719 100644
158201
{
159202
+ INVALID_PROCSIGNAL = -1, /* Must be first */
160203
+
161-
PROCSIG_CATCHUP_INTERRUPT, /* sinval catchup interrupt */
162-
PROCSIG_NOTIFY_INTERRUPT, /* listen/notify interrupt */
163-
PROCSIG_PARALLEL_MESSAGE, /* message from cooperating parallel backend */
204+
PROCSIG_CATCHUP_INTERRUPT, /* sinval catchup interrupt */
205+
PROCSIG_NOTIFY_INTERRUPT, /* listen/notify interrupt */
206+
PROCSIG_PARALLEL_MESSAGE, /* message from cooperating parallel backend */
164207
@@ -43,6 +47,14 @@ typedef enum
165-
PROCSIG_RECOVERY_CONFLICT_BUFFERPIN,
166-
PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK,
167-
208+
PROCSIG_RECOVERY_CONFLICT_BUFFERPIN,
209+
PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK,
210+
168211
+ PROCSIG_CUSTOM_1,
169212
+ /*
170213
+ * PROCSIG_CUSTOM_2,
@@ -173,34 +216,31 @@ index 5cb39697f38..c05f60fa719 100644
173216
+ */
174217
+ PROCSIG_CUSTOM_N = PROCSIG_CUSTOM_1 + NUM_CUSTOM_PROCSIGNALS - 1,
175218
+
176-
NUM_PROCSIGNALS /* Must be last! */
219+
NUM_PROCSIGNALS /* Must be last! */
177220
} ProcSignalReason;
178-
221+
179222
@@ -55,6 +67,8 @@ typedef enum
180-
*/
181-
PROCSIGNAL_BARRIER_PLACEHOLDER = 0
223+
*/
224+
PROCSIGNAL_BARRIER_PLACEHOLDER = 0
182225
} ProcSignalBarrierType;
183226
+/* Handler of custom process signal */
184227
+typedef void (*ProcSignalHandler_type) (void);
185-
228+
186229
/*
187230
* prototypes for functions in procsignal.c
188231
@@ -63,12 +77,15 @@ extern Size ProcSignalShmemSize(void);
189232
extern void ProcSignalShmemInit(void);
190-
233+
191234
extern void ProcSignalInit(int pss_idx);
192235
+extern ProcSignalReason
193236
+ RegisterCustomProcSignalHandler(ProcSignalHandler_type handler);
194237
extern int SendProcSignal(pid_t pid, ProcSignalReason reason,
195-
BackendId backendId);
196-
238+
BackendId backendId);
239+
197240
extern uint64 EmitProcSignalBarrier(ProcSignalBarrierType type);
198241
extern void WaitForProcSignalBarrier(uint64 generation);
199242
extern void ProcessProcSignalBarrier(void);
200243
+extern void CheckAndHandleCustomSignals(void);
201-
244+
202245
extern void procsignal_sigusr1_handler(SIGNAL_ARGS);
203-
204-
--
205-
2.25.1
206-
246+

patches/custom_signals_14.0.patch

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,30 @@
11
diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c
2-
index defb75a..4245d28 100644
2+
index defb75aa26a..cd7d44977ca 100644
33
--- a/src/backend/storage/ipc/procsignal.c
44
+++ b/src/backend/storage/ipc/procsignal.c
5-
@@ -95,6 +95,13 @@ typedef struct
6-
#define BARRIER_CLEAR_BIT(flags, type) \
5+
@@ -6,6 +6,7 @@
6+
*
7+
* Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
8+
* Portions Copyright (c) 1994, Regents of the University of California
9+
+ * Portions Copyright (c) 2021, Postgres Professional
10+
*
11+
* IDENTIFICATION
12+
* src/backend/storage/ipc/procsignal.c
13+
@@ -96,6 +97,13 @@ typedef struct
714
((flags) &= ~(((uint32) 1) << (uint32) (type)))
815

16+
static ProcSignalHeader *ProcSignal = NULL;
917
+#define IsCustomProcSignalReason(reason) \
1018
+ ((reason) >= PROCSIG_CUSTOM_1 && (reason) <= PROCSIG_CUSTOM_N)
1119
+
1220
+static bool CustomSignalPendings[NUM_CUSTOM_PROCSIGNALS];
1321
+static bool CustomSignalProcessing[NUM_CUSTOM_PROCSIGNALS];
1422
+static ProcSignalHandler_type CustomInterruptHandlers[NUM_CUSTOM_PROCSIGNALS];
1523
+
16-
static ProcSignalHeader *ProcSignal = NULL;
1724
static ProcSignalSlot *MyProcSignalSlot = NULL;
1825

19-
@@ -103,6 +110,8 @@ static void CleanupProcSignalState(int status, Datum arg);
26+
static bool CheckProcSignal(ProcSignalReason reason);
27+
@@ -103,6 +111,8 @@ static void CleanupProcSignalState(int status, Datum arg);
2028
static void ResetProcSignalBarrierBits(uint32 flags);
2129
static bool ProcessBarrierPlaceholder(void);
2230

@@ -25,7 +33,7 @@ index defb75a..4245d28 100644
2533
/*
2634
* ProcSignalShmemSize
2735
* Compute space needed for procsignal's shared memory
28-
@@ -246,6 +255,36 @@ CleanupProcSignalState(int status, Datum arg)
36+
@@ -246,6 +256,36 @@ CleanupProcSignalState(int status, Datum arg)
2937
slot->pss_pid = 0;
3038
}
3139

@@ -62,7 +70,7 @@ index defb75a..4245d28 100644
6270
/*
6371
* SendProcSignal
6472
* Send a signal to a Postgres process
65-
@@ -679,7 +718,62 @@ procsignal_sigusr1_handler(SIGNAL_ARGS)
73+
@@ -679,7 +719,72 @@ procsignal_sigusr1_handler(SIGNAL_ARGS)
6674
if (CheckProcSignal(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN))
6775
RecoveryConflictInterrupt(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN);
6876

@@ -107,6 +115,14 @@ index defb75a..4245d28 100644
107115
+{
108116
+ int i;
109117
+
118+
+ /*
119+
+ * This is invoked from ProcessInterrupts(), and since some of the
120+
+ * functions it calls contain CHECK_FOR_INTERRUPTS(), there is a potential
121+
+ * for recursive calls if more signals are received while this runs, so
122+
+ * let's block interrupts until done.
123+
+ */
124+
+ HOLD_INTERRUPTS();
125+
+
110126
+ /* Check on expiring of custom signals and call its handlers if exist */
111127
+ for (i = 0; i < NUM_CUSTOM_PROCSIGNALS; i++)
112128
+ {
@@ -124,23 +140,60 @@ index defb75a..4245d28 100644
124140
+ }
125141
+ }
126142
+ }
143+
+
144+
+ RESUME_INTERRUPTS();
127145
+}
128-
\ No newline at end of file
129146
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
130-
index 8cea10c..dd77c98 100644
147+
index 171f3a95006..e6fe26fb19a 100644
131148
--- a/src/backend/tcop/postgres.c
132149
+++ b/src/backend/tcop/postgres.c
133-
@@ -3364,6 +3364,8 @@ ProcessInterrupts(void)
134-
if (ParallelMessagePending)
135-
HandleParallelMessages();
150+
@@ -5,6 +5,7 @@
151+
*
152+
* Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
153+
* Portions Copyright (c) 1994, Regents of the University of California
154+
+ * Portions Copyright (c) 2021, Postgres Professional
155+
*
156+
*
157+
* IDENTIFICATION
158+
@@ -75,6 +76,7 @@
159+
#include "tcop/pquery.h"
160+
#include "tcop/tcopprot.h"
161+
#include "tcop/utility.h"
162+
+#include "utils/builtins.h"
163+
#include "utils/lsyscache.h"
164+
#include "utils/memutils.h"
165+
#include "utils/ps_status.h"
166+
@@ -3366,6 +3368,8 @@ ProcessInterrupts(void)
136167

137-
+ CheckAndHandleCustomSignals();
138-
+
139168
if (LogMemoryContextPending)
140169
ProcessLogMemoryContextInterrupt();
170+
+
171+
+ CheckAndHandleCustomSignals();
141172
}
173+
174+
175+
@@ -3711,7 +3715,7 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx,
176+
* postmaster/postmaster.c (the option sets should not conflict) and with
177+
* the common help() function in main/main.c.
178+
*/
179+
- while ((flag = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOPp:r:S:sTt:v:W:-:")) != -1)
180+
+ while ((flag = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOPp:r:S:sTt:v:W:Z-:")) != -1)
181+
{
182+
switch (flag)
183+
{
184+
@@ -3843,6 +3847,10 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx,
185+
SetConfigOption("post_auth_delay", optarg, ctx, gucsource);
186+
break;
187+
188+
+ case 'Z':
189+
+ /* ignored for consistency with the postmaster */
190+
+ break;
191+
+
192+
case 'c':
193+
case '-':
194+
{
142195
diff --git a/src/include/storage/procsignal.h b/src/include/storage/procsignal.h
143-
index eec186b..74af186 100644
196+
index eec186be2ee..74af186bf53 100644
144197
--- a/src/include/storage/procsignal.h
145198
+++ b/src/include/storage/procsignal.h
146199
@@ -17,6 +17,8 @@
@@ -201,6 +254,3 @@ index eec186b..74af186 100644
201254

202255
extern void procsignal_sigusr1_handler(SIGNAL_ARGS);
203256

204-
--
205-
2.25.1
206-

patches/custom_signals_15.0.patch

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ index defb75a..4245d28 100644
107107
+{
108108
+ int i;
109109
+
110+
+ /*
111+
+ * This is invoked from ProcessInterrupts(), and since some of the
112+
+ * functions it calls contain CHECK_FOR_INTERRUPTS(), there is a potential
113+
+ * for recursive calls if more signals are received while this runs, so
114+
+ * let's block interrupts until done.
115+
+ */
116+
+ HOLD_INTERRUPTS();
117+
+
110118
+ /* Check on expiring of custom signals and call its handlers if exist */
111119
+ for (i = 0; i < NUM_CUSTOM_PROCSIGNALS; i++)
112120
+ {
@@ -124,6 +132,8 @@ index defb75a..4245d28 100644
124132
+ }
125133
+ }
126134
+ }
135+
+
136+
+ RESUME_INTERRUPTS();
127137
+}
128138
\ No newline at end of file
129139
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy