@@ -130,6 +130,9 @@ static volatile sig_atomic_t waiting = false;
130
130
static int selfpipe_readfd = -1;
131
131
static int selfpipe_writefd = -1;
132
132
133
+ /* Process owning the self-pipe --- needed for checking purposes */
134
+ static int selfpipe_owner_pid = 0;
135
+
133
136
/* Private function prototypes */
134
137
static void sendSelfPipeByte(void);
135
138
static void drainSelfPipe(void);
@@ -158,31 +161,72 @@ InitializeLatchSupport(void)
158
161
#ifndef WIN32
159
162
int pipefd[2];
160
163
161
- Assert(selfpipe_readfd == -1);
164
+ if (IsUnderPostmaster)
165
+ {
166
+ /*
167
+ * We might have inherited connections to a self-pipe created by the
168
+ * postmaster. It's critical that child processes create their own
169
+ * self-pipes, of course, and we really want them to close the
170
+ * inherited FDs for safety's sake.
171
+ */
172
+ if (selfpipe_owner_pid != 0)
173
+ {
174
+ /* Assert we go through here but once in a child process */
175
+ Assert(selfpipe_owner_pid != MyProcPid);
176
+ /* Release postmaster's pipe FDs; ignore any error */
177
+ (void) close(selfpipe_readfd);
178
+ (void) close(selfpipe_writefd);
179
+ /* Clean up, just for safety's sake; we'll set these below */
180
+ selfpipe_readfd = selfpipe_writefd = -1;
181
+ selfpipe_owner_pid = 0;
182
+ }
183
+ else
184
+ {
185
+ /*
186
+ * Postmaster didn't create a self-pipe ... or else we're in an
187
+ * EXEC_BACKEND build, in which case it doesn't matter since the
188
+ * postmaster's pipe FDs were closed by the action of FD_CLOEXEC.
189
+ */
190
+ Assert(selfpipe_readfd == -1);
191
+ }
192
+ }
193
+ else
194
+ {
195
+ /* In postmaster or standalone backend, assert we do this but once */
196
+ Assert(selfpipe_readfd == -1);
197
+ Assert(selfpipe_owner_pid == 0);
198
+ }
162
199
163
200
/*
164
201
* Set up the self-pipe that allows a signal handler to wake up the
165
202
* select() in WaitLatch. Make the write-end non-blocking, so that
166
203
* SetLatch won't block if the event has already been set many times
167
204
* filling the kernel buffer. Make the read-end non-blocking too, so that
168
205
* we can easily clear the pipe by reading until EAGAIN or EWOULDBLOCK.
206
+ * Also, make both FDs close-on-exec, since we surely do not want any
207
+ * child processes messing with them.
169
208
*/
170
209
if (pipe(pipefd) < 0)
171
210
elog(FATAL, "pipe() failed: %m");
172
211
if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) == -1)
173
- elog(FATAL, "fcntl() failed on read-end of self-pipe: %m");
212
+ elog(FATAL, "fcntl(F_SETFL ) failed on read-end of self-pipe: %m");
174
213
if (fcntl(pipefd[1], F_SETFL, O_NONBLOCK) == -1)
175
- elog(FATAL, "fcntl() failed on write-end of self-pipe: %m");
214
+ elog(FATAL, "fcntl(F_SETFL) failed on write-end of self-pipe: %m");
215
+ if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) == -1)
216
+ elog(FATAL, "fcntl(F_SETFD) failed on read-end of self-pipe: %m");
217
+ if (fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) == -1)
218
+ elog(FATAL, "fcntl(F_SETFD) failed on write-end of self-pipe: %m");
176
219
177
220
selfpipe_readfd = pipefd[0];
178
221
selfpipe_writefd = pipefd[1];
222
+ selfpipe_owner_pid = MyProcPid;
179
223
#else
180
224
/* currently, nothing to do here for Windows */
181
225
#endif
182
226
}
183
227
184
228
/*
185
- * Initialize a backend -local latch.
229
+ * Initialize a process -local latch.
186
230
*/
187
231
void
188
232
InitLatch(volatile Latch *latch)
@@ -193,7 +237,7 @@ InitLatch(volatile Latch *latch)
193
237
194
238
#ifndef WIN32
195
239
/* Assert InitializeLatchSupport has been called in this process */
196
- Assert(selfpipe_readfd >= 0);
240
+ Assert(selfpipe_readfd >= 0 && selfpipe_owner_pid == MyProcPid );
197
241
#else
198
242
latch->event = CreateEvent(NULL, TRUE, FALSE, NULL);
199
243
if (latch->event == NULL)
@@ -211,6 +255,10 @@ InitLatch(volatile Latch *latch)
211
255
* containing the latch with ShmemInitStruct. (The Unix implementation
212
256
* doesn't actually require that, but the Windows one does.) Because of
213
257
* this restriction, we have no concurrency issues to worry about here.
258
+ *
259
+ * Note that other handles created in this module are never marked as
260
+ * inheritable. Thus we do not need to worry about cleaning up child
261
+ * process references to postmaster-private latches or WaitEventSets.
214
262
*/
215
263
void
216
264
InitSharedLatch(volatile Latch *latch)
@@ -256,7 +304,7 @@ OwnLatch(volatile Latch *latch)
256
304
257
305
#ifndef WIN32
258
306
/* Assert InitializeLatchSupport has been called in this process */
259
- Assert(selfpipe_readfd >= 0);
307
+ Assert(selfpipe_readfd >= 0 && selfpipe_owner_pid == MyProcPid );
260
308
#endif
261
309
262
310
if (latch->owner_pid != 0)
@@ -289,7 +337,7 @@ DisownLatch(volatile Latch *latch)
289
337
* is incurred when WL_TIMEOUT is given, so avoid using a timeout if possible.
290
338
*
291
339
* The latch must be owned by the current process, ie. it must be a
292
- * backend -local latch initialized with InitLatch, or a shared latch
340
+ * process -local latch initialized with InitLatch, or a shared latch
293
341
* associated with the current process by calling OwnLatch.
294
342
*
295
343
* Returns bit mask indicating which condition(s) caused the wake-up. Note
@@ -526,9 +574,9 @@ CreateWaitEventSet(MemoryContext context, int nevents)
526
574
set->nevents_space = nevents;
527
575
528
576
#if defined(WAIT_USE_EPOLL)
529
- set->epoll_fd = epoll_create(nevents );
577
+ set->epoll_fd = epoll_create1(EPOLL_CLOEXEC );
530
578
if (set->epoll_fd < 0)
531
- elog(ERROR, "epoll_create failed: %m");
579
+ elog(ERROR, "epoll_create1 failed: %m");
532
580
#elif defined(WAIT_USE_WIN32)
533
581
534
582
/*
@@ -549,6 +597,12 @@ CreateWaitEventSet(MemoryContext context, int nevents)
549
597
550
598
/*
551
599
* Free a previously created WaitEventSet.
600
+ *
601
+ * Note: preferably, this shouldn't have to free any resources that could be
602
+ * inherited across an exec(). If it did, we'd likely leak those resources in
603
+ * many scenarios. For the epoll case, we ensure that by setting FD_CLOEXEC
604
+ * when the FD is created. For the Windows case, we assume that the handles
605
+ * involved are non-inheritable.
552
606
*/
553
607
void
554
608
FreeWaitEventSet(WaitEventSet *set)
@@ -595,7 +649,7 @@ FreeWaitEventSet(WaitEventSet *set)
595
649
* used to modify previously added wait events using ModifyWaitEvent().
596
650
*
597
651
* In the WL_LATCH_SET case the latch must be owned by the current process,
598
- * i.e. it must be a backend -local latch initialized with InitLatch, or a
652
+ * i.e. it must be a process -local latch initialized with InitLatch, or a
599
653
* shared latch associated with the current process by calling OwnLatch.
600
654
*
601
655
* In the WL_SOCKET_READABLE/WRITEABLE case, EOF and error conditions are
0 commit comments