From 7ca80af640d41ffdaee49e756535ecdc3cc3b151 Mon Sep 17 00:00:00 2001 From: Varik Matevosyan Date: Wed, 20 Nov 2024 17:41:56 +0400 Subject: [PATCH] Check wakeup_flags from `wait_latch` function to exit on `WL_POSTMASTER_DEATH` (#1938) There are some cases when the `wait_latch` loop in background worker is not being interrupted after the postmaster was exited. It can be reproduced by running postgres directly using `/opt/homebrew/opt/postgresql@17/bin/postgres -D /opt/homebrew/var/postgresql@17` and after the background worker will be started you will need to send `SIGKILL` to the postmaster process. (the issue is not reproducible when managing postgres via `pg_ctl`, I have encountered this issue during local development as homebrew service runs postgres directly using `postgres` binary) Then you can see that the postgres will be exited, but background worker process will remain active. > Make sure the WL_POSTMASTER_DEATH flag is set when calling that function, and verify the return code for a prompt exit in the emergency case that postgres itself has terminated. (see https://github.com/pgcentralfoundation/pgrx/pull/1938 for an example) --- pgrx/src/bgworkers.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pgrx/src/bgworkers.rs b/pgrx/src/bgworkers.rs index 74e3f0cf8..a91490dbb 100644 --- a/pgrx/src/bgworkers.rs +++ b/pgrx/src/bgworkers.rs @@ -163,14 +163,16 @@ impl BackgroundWorker { unsafe { assert!(!pg_sys::MyBgworkerEntry.is_null(), "BackgroundWorker associated functions can only be called from a registered background worker"); } - match timeout { + let wakeup_flags = match timeout { Some(t) => wait_latch( t.as_millis().try_into().unwrap(), WLflags::WL_LATCH_SET | WLflags::WL_TIMEOUT | WLflags::WL_POSTMASTER_DEATH, ), None => wait_latch(0, WLflags::WL_LATCH_SET | WLflags::WL_POSTMASTER_DEATH), }; - !BackgroundWorker::sigterm_received() + + let postmaster_died = (wakeup_flags & pg_sys::WL_POSTMASTER_DEATH as i32) != 0; + !BackgroundWorker::sigterm_received() && !postmaster_died } /// Is this `BackgroundWorker` allowed to continue?