From 14cddee9cce349d4bf024316e014ccf891c39cef Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Mon, 18 Mar 2024 11:35:01 +0200 Subject: [PATCH] Split registration of Win32 deadchild callback to separate function 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 | 50 +++++++++++++++++------------ 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index a8793fcb0bc..a373e82dd66 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -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; + /* Set up notification when the child process dies */ + pgwin32_register_deadchild_callback(pi.hProcess, 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()))); - - /* 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 */ /*