Split registration of Win32 deadchild callback to separate function
authorHeikki Linnakangas <[email protected]>
Mon, 18 Mar 2024 09:35:01 +0000 (11:35 +0200)
committerHeikki Linnakangas <[email protected]>
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 */
 
 /*