Checks in RegisterBackgroundWorker.()
Heikki Linnakangas <hlinnaka@iki.fi>
From: Heikki Linnakangas <hlinnaka@iki.fi>
To: pgsql-hackers <pgsql-hackers@postgresql.org>
Date: 2023-08-24T15:15:33Z
Lists: pgsql-hackers
Attachments
- 0001-Clarify-the-checks-in-RegisterBackgroundWorker.patch (text/x-patch) patch 0001
- 0002-Allocate-Backend-structs-in-PostmasterContext.patch (text/x-patch) patch 0002
- 0003-Fix-misleading-comment-on-StartBackgroundWorker.patch (text/x-patch) patch 0003
The first patch on my "Refactoring backend fork+exec code" thread [0] changes the allocations of BackgroundWorkerList from plain malloc() to MemoryContextAlloc(PostmasterContext). However, that actually caused a segfault in worker_spi tests in EXEC_BACKEND mode. BackgroundWorkerList is a postmaster-private data structure and should not be accessed in backends. That assumption failed in RegisterBackgroundWorker(). When you put worker_spi in shared_preload_libraries, its _PG_init() function calls RegisterBackgroundWorker(), as expected. But in EXEC_BACKEND mode, the library is loaded *again* in each backend process, and each of those loads also call RegisterBackgroundWorker(). It's too late to correctly register any static background workers at that stage, but RegisterBackgroundWorker() still goes through the motions and adds the element to BackgroundWorkerList. If you change the malloc() to MemoryContextAlloc(PostmasterContext), it segfaults because PostmasterContext == NULL in a backend process. In summary, RegisterBackgroundWorker() is doing some questionable and useless work, when a shared preload library is loaded to a backend process in EXEC_BACKEND mode. Attached patches: 1. Tighten/clarify those checks. See also commit message for details. 2. The patch from the other thread to switch to MemoryContextAlloc(PostmasterContext) 3. A fix for a highly misleading comment in the same file. Any comments? [0] https://www.postgresql.org/message-id/flat/7a59b073-5b5b-151e-7ed3-8b01ff7ce9ef%40iki.fi P.S. In addition to those, I also considered these changes but didn't implement them yet: - Change RegisterBackgroundWorker() to return true/false to indicate whether the registration succeeded. Currently, the caller has no way of knowing. In many cases, I think even an ERROR and refusing to start up the server would be appropriate. But at least we should let the caller know and decide. - Add "Assert(am_postmaster)" assertions to the functions in bgworker.c that are only supposed to be called in postmaster process. The functions have good explicit comments on that, but wouldn't hurt to also assert. (There is no 'am_postmaster' flag, the equivalent is actually (IsPostmasterEnvironment && !IsUnderPostmaster), but perhaps we should define a macro or flag for that) -- Heikki Linnakangas Neon (https://neon.tech)
Commits
-
Rename StartBackgroundWorker() to BackgroundWorkerMain().
- 637109d13ab2 17.0 landed
-
Allocate Backend structs in PostmasterContext.
- 0bbafb534275 17.0 landed
-
Clarify the checks in RegisterBackgroundWorker.
- 1ca312686e4c 17.0 landed