Hi, I tried to implement a static background(bg) worker without shared memory access (BGWORKER_SHMEM_ACCESS), it worked fine on Linux machine where EXEC_BACKEND is not defined(thanks to the fork() implementation which does great job to get the global state from the postmaster(parent) to bg worker(child)).
However, the problem arised, when I switched to EXEC_BACKEND mode, it seems it doesn't. I digged a bit and the following is my analysis: for EXEC_BACKEND cases, (say on Windows platforms where fork() doesn't exist) the way postmaster creates a background worker is entirely different. It is done through SubPostmasterMain and the global state from the postmaster is shared with the background worker via shared memory. MyLatch variable also gets created in shared mode. And having no shared memory access for the worker for EXEC_BACKEND cases(in StartBackgroundWorker, the shared memory segments get detached), the worker fails to receive all the global state from the postmaster. Looks like the background worker needs to have the BGWORKER_SHMEM_ACCESS flag while registering for EXEC_BACKEND cases. Please feel free to correct me if I miss anything here. If the above analysis looks fine, then please find a patch that adds some info in bgworker.sgml and bgworker.h. Thoughts? With Regards, Bharath Rupireddy. EnterpriseDB: http://www.enterprisedb.com
From 6117cf28a14ed1861f9cae2f83fccadf75504c43 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy <bharath.rupireddy@enterprisedb.com> Date: Fri, 31 Jul 2020 16:42:05 +0530 Subject: [PATCH v1] Background worker shared memory access for EXEC_BACKEND cases For EXEC_BACKEND cases, (say on Windows platforms where fork() doesn't exist) the way postmaster creates a background worker is different. It is done through SubPostmasterMain and the global state from the postmaster is shared with the background worker via shared memory. And having no shared memory access for the worker for EXEC_BACKEND cases, (in StartBackgroundWorker, the shared memory segments get detached) the worker fails to receive all the global state from the postmaster. Looks like the background worker needs to have the BGWORKER_SHMEM_ACCESS flag while registering for EXEC_BACKEND cases. --- doc/src/sgml/bgworker.sgml | 13 ++++++++++++- src/include/postmaster/bgworker.h | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml index 6e1cf121de..7e2b22eedc 100644 --- a/doc/src/sgml/bgworker.sgml +++ b/doc/src/sgml/bgworker.sgml @@ -89,7 +89,18 @@ typedef struct BackgroundWorker cannot access any of <productname>PostgreSQL's</productname> shared data structures, such as heavyweight or lightweight locks, shared buffers, or any custom data structures which the worker itself may - wish to create and use. + wish to create and use. If the background worker doesn't need shared + memory access, on non-EXEC_BACKEND cases (such as Unix/Linux platforms) + it is fine, since the worker gets all the global state required from the + postmaster by the way the fork() is implemented. However, for EXEC_BACKEND + cases, (say on Windows platforms where fork() doesn't exist) the way + postmaster creates a background worker is different. It is done through + SubPostmasterMain and the global state from the postmaster is shared + with the background worker via shared memory. And having no shared memory + access for the worker for EXEC_BACKEND cases, (in StartBackgroundWorker, + the shared memory segments get detached) the worker fails to receive all the + global state from the postmaster. Hence the background worker needs to have + BGWORKER_SHMEM_ACCESS flag while registering for EXEC_BACKEND cases. </para> </listitem> </varlistentry> diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h index 4c6ebaa41b..88d1ea74f0 100644 --- a/src/include/postmaster/bgworker.h +++ b/src/include/postmaster/bgworker.h @@ -51,6 +51,20 @@ */ #define BGWORKER_SHMEM_ACCESS 0x0001 +/* + * If the background worker doesn't need shared memory access, on non-EXEC_BACKEND + * cases (such as Unix/Linux platforms) it is fine, since the worker gets all the + * global state required from the postmaster by the way the fork() is implemented. + * However, for EXEC_BACKEND cases, (say on Windows platforms where fork() doesn't + * exist) the way postmaster creates a background worker is different. It is done + * through SubPostmasterMain and the global state from the postmaster is shared + * with the background worker via shared memory. And having no shared memory access + * for the worker for EXEC_BACKEND cases, (in StartBackgroundWorker, the shared + * memory segments get detached) the worker fails to receive all the global state + * from the postmaster. Hence the background worker needs to have BGWORKER_SHMEM_ACCESS + * flag while registering for EXEC_BACKEND cases. + */ + /* * This flag means the bgworker requires a database connection. The connection * is not established automatically; the worker must establish it later. -- 2.25.1