Split registration of Win32 deadchild callback to separate function
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 18 Mar 2024 09:35:01 +0000 (11:35 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 18 Mar 2024 09:35:01 +0000 (11:35 +0200)
The next commit will move the internal_forkexec() function to a
different source file, but it makes sense to keep all the code related
to the win32 waitpid() emulation in postmaster.c. Split it off to a
separate function now, to make the next commit more mechanical.

Reviewed-by: Tristan Partin, Andres Freund
Discussion: https://www.postgresql.org/message-id/7a59b073-5b5b-151e-7ed3-8b01ff7ce9ef@iki.fi

src/backend/postmaster/postmaster.c

index a8793fcb0bc4a87a1adbd48b0acb0f4105712a19..a373e82dd66c2aac18e47497bf05ddee2c40d8a3 100644 (file)
@@ -476,6 +476,7 @@ static void MaybeStartSlotSyncWorker(void);
 
 static pid_t waitpid(pid_t pid, int *exitstatus, int options);
 static void WINAPI pgwin32_deadchild_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired);
+static void pgwin32_register_deadchild_callback(HANDLE procHandle, DWORD procId);
 
 static HANDLE win32ChildQueue;
 
@@ -4623,7 +4624,6 @@ internal_forkexec(int argc, char *argv[], ClientSocket *client_sock, BackgroundW
        BackendParameters *param;
        SECURITY_ATTRIBUTES sa;
        char            paramHandleStr[32];
-       win32_deadchild_waitinfo *childinfo;
 
        /* Make sure caller set up argv properly */
        Assert(argc >= 3);
@@ -4783,26 +4783,10 @@ retry:
                return -1;
        }
 
-       /*
-        * Queue a waiter to signal when this child dies. The wait will be handled
-        * automatically by an operating system thread pool.  The memory will be
-        * freed by a later call to waitpid().
-        */
-       childinfo = palloc(sizeof(win32_deadchild_waitinfo));
-       childinfo->procHandle = pi.hProcess;
-       childinfo->procId = pi.dwProcessId;
-
-       if (!RegisterWaitForSingleObject(&childinfo->waitHandle,
-                                                                        pi.hProcess,
-                                                                        pgwin32_deadchild_callback,
-                                                                        childinfo,
-                                                                        INFINITE,
-                                                                        WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD))
-               ereport(FATAL,
-                               (errmsg_internal("could not register process for wait: error code %lu",
-                                                                GetLastError())));
+       /* Set up notification when the child process dies */
+       pgwin32_register_deadchild_callback(pi.hProcess, pi.dwProcessId);
 
-       /* Don't close pi.hProcess here - waitpid() needs access to it */
+       /* Don't close pi.hProcess, it's owned by the deadchild callback now */
 
        CloseHandle(pi.hThread);
 
@@ -6526,6 +6510,32 @@ pgwin32_deadchild_callback(PVOID lpParameter, BOOLEAN TimerOrWaitFired)
        /* Queue SIGCHLD signal. */
        pg_queue_signal(SIGCHLD);
 }
+
+/*
+ * Queue a waiter to signal when this child dies.  The wait will be handled
+ * automatically by an operating system thread pool.  The memory and the
+ * process handle will be freed by a later call to waitpid().
+ */
+static void
+pgwin32_register_deadchild_callback(HANDLE procHandle, DWORD procId)
+{
+       win32_deadchild_waitinfo *childinfo;
+
+       childinfo = palloc(sizeof(win32_deadchild_waitinfo));
+       childinfo->procHandle = procHandle;
+       childinfo->procId = procId;
+
+       if (!RegisterWaitForSingleObject(&childinfo->waitHandle,
+                                                                        procHandle,
+                                                                        pgwin32_deadchild_callback,
+                                                                        childinfo,
+                                                                        INFINITE,
+                                                                        WT_EXECUTEONLYONCE | WT_EXECUTEINWAITTHREAD))
+               ereport(FATAL,
+                               (errmsg_internal("could not register process for wait: error code %lu",
+                                                                GetLastError())));
+}
+
 #endif                                                 /* WIN32 */
 
 /*