@@ -118,6 +118,9 @@ static volatile sig_atomic_t waiting = false;
118
118
static int selfpipe_readfd = -1 ;
119
119
static int selfpipe_writefd = -1 ;
120
120
121
+ /* Process owning the self-pipe --- needed for checking purposes */
122
+ static int selfpipe_owner_pid = 0 ;
123
+
121
124
/* Private function prototypes */
122
125
static void sendSelfPipeByte (void );
123
126
static void drainSelfPipe (void );
@@ -146,31 +149,72 @@ InitializeLatchSupport(void)
146
149
#ifndef WIN32
147
150
int pipefd [2 ];
148
151
149
- Assert (selfpipe_readfd == -1 );
152
+ if (IsUnderPostmaster )
153
+ {
154
+ /*
155
+ * We might have inherited connections to a self-pipe created by the
156
+ * postmaster. It's critical that child processes create their own
157
+ * self-pipes, of course, and we really want them to close the
158
+ * inherited FDs for safety's sake.
159
+ */
160
+ if (selfpipe_owner_pid != 0 )
161
+ {
162
+ /* Assert we go through here but once in a child process */
163
+ Assert (selfpipe_owner_pid != MyProcPid );
164
+ /* Release postmaster's pipe FDs; ignore any error */
165
+ (void ) close (selfpipe_readfd );
166
+ (void ) close (selfpipe_writefd );
167
+ /* Clean up, just for safety's sake; we'll set these below */
168
+ selfpipe_readfd = selfpipe_writefd = -1 ;
169
+ selfpipe_owner_pid = 0 ;
170
+ }
171
+ else
172
+ {
173
+ /*
174
+ * Postmaster didn't create a self-pipe ... or else we're in an
175
+ * EXEC_BACKEND build, in which case it doesn't matter since the
176
+ * postmaster's pipe FDs were closed by the action of FD_CLOEXEC.
177
+ */
178
+ Assert (selfpipe_readfd == -1 );
179
+ }
180
+ }
181
+ else
182
+ {
183
+ /* In postmaster or standalone backend, assert we do this but once */
184
+ Assert (selfpipe_readfd == -1 );
185
+ Assert (selfpipe_owner_pid == 0 );
186
+ }
150
187
151
188
/*
152
189
* Set up the self-pipe that allows a signal handler to wake up the
153
190
* poll()/epoll_wait() in WaitLatch. Make the write-end non-blocking, so
154
191
* that SetLatch won't block if the event has already been set many times
155
192
* filling the kernel buffer. Make the read-end non-blocking too, so that
156
193
* we can easily clear the pipe by reading until EAGAIN or EWOULDBLOCK.
194
+ * Also, make both FDs close-on-exec, since we surely do not want any
195
+ * child processes messing with them.
157
196
*/
158
197
if (pipe (pipefd ) < 0 )
159
198
elog (FATAL , "pipe() failed: %m" );
160
199
if (fcntl (pipefd [0 ], F_SETFL , O_NONBLOCK ) == -1 )
161
- elog (FATAL , "fcntl() failed on read-end of self-pipe: %m" );
200
+ elog (FATAL , "fcntl(F_SETFL ) failed on read-end of self-pipe: %m" );
162
201
if (fcntl (pipefd [1 ], F_SETFL , O_NONBLOCK ) == -1 )
163
- elog (FATAL , "fcntl() failed on write-end of self-pipe: %m" );
202
+ elog (FATAL , "fcntl(F_SETFL) failed on write-end of self-pipe: %m" );
203
+ if (fcntl (pipefd [0 ], F_SETFD , FD_CLOEXEC ) == -1 )
204
+ elog (FATAL , "fcntl(F_SETFD) failed on read-end of self-pipe: %m" );
205
+ if (fcntl (pipefd [1 ], F_SETFD , FD_CLOEXEC ) == -1 )
206
+ elog (FATAL , "fcntl(F_SETFD) failed on write-end of self-pipe: %m" );
164
207
165
208
selfpipe_readfd = pipefd [0 ];
166
209
selfpipe_writefd = pipefd [1 ];
210
+ selfpipe_owner_pid = MyProcPid ;
167
211
#else
168
212
/* currently, nothing to do here for Windows */
169
213
#endif
170
214
}
171
215
172
216
/*
173
- * Initialize a backend -local latch.
217
+ * Initialize a process -local latch.
174
218
*/
175
219
void
176
220
InitLatch (volatile Latch * latch )
@@ -181,7 +225,7 @@ InitLatch(volatile Latch *latch)
181
225
182
226
#ifndef WIN32
183
227
/* Assert InitializeLatchSupport has been called in this process */
184
- Assert (selfpipe_readfd >= 0 );
228
+ Assert (selfpipe_readfd >= 0 && selfpipe_owner_pid == MyProcPid );
185
229
#else
186
230
latch -> event = CreateEvent (NULL , TRUE, FALSE, NULL );
187
231
if (latch -> event == NULL )
@@ -199,6 +243,10 @@ InitLatch(volatile Latch *latch)
199
243
* containing the latch with ShmemInitStruct. (The Unix implementation
200
244
* doesn't actually require that, but the Windows one does.) Because of
201
245
* this restriction, we have no concurrency issues to worry about here.
246
+ *
247
+ * Note that other handles created in this module are never marked as
248
+ * inheritable. Thus we do not need to worry about cleaning up child
249
+ * process references to postmaster-private latches or WaitEventSets.
202
250
*/
203
251
void
204
252
InitSharedLatch (volatile Latch * latch )
@@ -244,7 +292,7 @@ OwnLatch(volatile Latch *latch)
244
292
245
293
#ifndef WIN32
246
294
/* Assert InitializeLatchSupport has been called in this process */
247
- Assert (selfpipe_readfd >= 0 );
295
+ Assert (selfpipe_readfd >= 0 && selfpipe_owner_pid == MyProcPid );
248
296
#endif
249
297
250
298
if (latch -> owner_pid != 0 )
@@ -277,7 +325,7 @@ DisownLatch(volatile Latch *latch)
277
325
* is incurred when WL_TIMEOUT is given, so avoid using a timeout if possible.
278
326
*
279
327
* The latch must be owned by the current process, ie. it must be a
280
- * backend -local latch initialized with InitLatch, or a shared latch
328
+ * process -local latch initialized with InitLatch, or a shared latch
281
329
* associated with the current process by calling OwnLatch.
282
330
*
283
331
* Returns bit mask indicating which condition(s) caused the wake-up. Note
@@ -517,9 +565,9 @@ CreateWaitEventSet(MemoryContext context, int nevents)
517
565
set -> nevents_space = nevents ;
518
566
519
567
#if defined(WAIT_USE_EPOLL )
520
- set -> epoll_fd = epoll_create ( nevents );
568
+ set -> epoll_fd = epoll_create1 ( EPOLL_CLOEXEC );
521
569
if (set -> epoll_fd < 0 )
522
- elog (ERROR , "epoll_create failed: %m" );
570
+ elog (ERROR , "epoll_create1 failed: %m" );
523
571
#elif defined(WAIT_USE_WIN32 )
524
572
525
573
/*
@@ -540,6 +588,12 @@ CreateWaitEventSet(MemoryContext context, int nevents)
540
588
541
589
/*
542
590
* Free a previously created WaitEventSet.
591
+ *
592
+ * Note: preferably, this shouldn't have to free any resources that could be
593
+ * inherited across an exec(). If it did, we'd likely leak those resources in
594
+ * many scenarios. For the epoll case, we ensure that by setting FD_CLOEXEC
595
+ * when the FD is created. For the Windows case, we assume that the handles
596
+ * involved are non-inheritable.
543
597
*/
544
598
void
545
599
FreeWaitEventSet (WaitEventSet * set )
@@ -586,7 +640,7 @@ FreeWaitEventSet(WaitEventSet *set)
586
640
* used to modify previously added wait events using ModifyWaitEvent().
587
641
*
588
642
* In the WL_LATCH_SET case the latch must be owned by the current process,
589
- * i.e. it must be a backend -local latch initialized with InitLatch, or a
643
+ * i.e. it must be a process -local latch initialized with InitLatch, or a
590
644
* shared latch associated with the current process by calling OwnLatch.
591
645
*
592
646
* In the WL_SOCKET_READABLE/WRITEABLE case, EOF and error conditions are
0 commit comments