aboutsummaryrefslogtreecommitdiff
path: root/src/backend/postmaster/postmaster.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/postmaster/postmaster.c')
-rw-r--r--src/backend/postmaster/postmaster.c70
1 files changed, 40 insertions, 30 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 2552327d904..71198b72c83 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -4811,7 +4811,7 @@ retry:
(errmsg_internal("could not register process for wait: error code %lu",
GetLastError())));
- /* Don't close pi.hProcess here - the wait thread needs access to it */
+ /* Don't close pi.hProcess here - waitpid() needs access to it */
CloseHandle(pi.hThread);
@@ -6421,36 +6421,21 @@ ShmemBackendArrayRemove(Backend *bn)
static pid_t
waitpid(pid_t pid, int *exitstatus, int options)
{
+ win32_deadchild_waitinfo *childinfo;
+ DWORD exitcode;
DWORD dwd;
ULONG_PTR key;
OVERLAPPED *ovl;
- /*
- * Check if there are any dead children. If there are, return the pid of
- * the first one that died.
- */
- if (GetQueuedCompletionStatus(win32ChildQueue, &dwd, &key, &ovl, 0))
+ /* Try to consume one win32_deadchild_waitinfo from the queue. */
+ if (!GetQueuedCompletionStatus(win32ChildQueue, &dwd, &key, &ovl, 0))
{
- *exitstatus = (int) key;
- return dwd;
+ errno = EAGAIN;
+ return -1;
}
- return -1;
-}
-
-/*
- * Note! Code below executes on a thread pool! All operations must
- * be thread safe! Note that elog() and friends must *not* be used.
- */
-static void WINAPI
-pgwin32_deadchild_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
-{
- win32_deadchild_waitinfo *childinfo = (win32_deadchild_waitinfo *) lpParameter;
- DWORD exitcode;
-
- if (TimerOrWaitFired)
- return; /* timeout. Should never happen, since we use
- * INFINITE as timeout value. */
+ childinfo = (win32_deadchild_waitinfo *) key;
+ pid = childinfo->procId;
/*
* Remove handle from wait - required even though it's set to wait only
@@ -6466,13 +6451,11 @@ pgwin32_deadchild_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
write_stderr("could not read exit code for process\n");
exitcode = 255;
}
-
- if (!PostQueuedCompletionStatus(win32ChildQueue, childinfo->procId, (ULONG_PTR) exitcode, NULL))
- write_stderr("could not post child completion status\n");
+ *exitstatus = exitcode;
/*
- * Handle is per-process, so we close it here instead of in the
- * originating thread
+ * Close the process handle. Only after this point can the PID can be
+ * recycled by the kernel.
*/
CloseHandle(childinfo->procHandle);
@@ -6482,7 +6465,34 @@ pgwin32_deadchild_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
*/
free(childinfo);
- /* Queue SIGCHLD signal */
+ return pid;
+}
+
+/*
+ * Note! Code below executes on a thread pool! All operations must
+ * be thread safe! Note that elog() and friends must *not* be used.
+ */
+static void WINAPI
+pgwin32_deadchild_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
+{
+ /* Should never happen, since we use INFINITE as timeout value. */
+ if (TimerOrWaitFired)
+ return;
+
+ /*
+ * Post the win32_deadchild_waitinfo object for waitpid() to deal with. If
+ * that fails, we leak the object, but we also leak a whole process and
+ * get into an unrecoverable state, so there's not much point in worrying
+ * about that. We'd like to panic, but we can't use that infrastructure
+ * from this thread.
+ */
+ if (!PostQueuedCompletionStatus(win32ChildQueue,
+ 0,
+ (ULONG_PTR) lpParameter,
+ NULL))
+ write_stderr("could not post child completion status\n");
+
+ /* Queue SIGCHLD signal. */
pg_queue_signal(SIGCHLD);
}
#endif /* WIN32 */