From 0a94c52409be7e48f2b03c4e088e4117a71abbe9 Mon Sep 17 00:00:00 2001 From: Shihao Zhong Date: Sat, 12 Sep 2026 08:46:49 -0400 Subject: [PATCH v3 1/2] Pass the backend's timeout settings to the REPACK decoding worker The worker connects as the table owner in a new session, so a role- or database-level lock_timeout applies to it and cancels its wait for older transactions, and the user running REPACK cannot override it. The same holds for transaction_timeout, because the worker's transaction spans the whole command. Pass the values in effect in the backend through the shared memory segment the worker already attaches to, so that a session-level SET reaches it too. --- src/backend/commands/repack.c | 4 ++++ src/backend/commands/repack_worker.c | 19 +++++++++++++++++++ src/include/commands/repack_internal.h | 4 ++++ 3 files changed, 27 insertions(+) diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c index 83168a4e6f3..139efccb1d5 100644 --- a/src/backend/commands/repack.c +++ b/src/backend/commands/repack.c @@ -3698,6 +3698,10 @@ start_repack_decoding_worker(Oid relid) shared->backend_pid = MyProcPid; shared->backend_proc_number = MyProcNumber; + /* Pass our timeouts to the worker. See RepackWorkerMain(). */ + shared->lock_timeout = LockTimeout; + shared->transaction_timeout = TransactionTimeout; + mq = shm_mq_create((char *) BUFFERALIGN(shared->error_queue), REPACK_ERROR_QUEUE_SIZE); shm_mq_set_receiver(mq, MyProc); diff --git a/src/backend/commands/repack_worker.c b/src/backend/commands/repack_worker.c index b4ba9cfc67b..05139429053 100644 --- a/src/backend/commands/repack_worker.c +++ b/src/backend/commands/repack_worker.c @@ -26,6 +26,7 @@ #include "storage/ipc.h" #include "storage/proc.h" #include "tcop/tcopprot.h" +#include "utils/guc.h" #include "utils/memutils.h" #define PGREPACK_PLUGIN "pgrepack" @@ -66,6 +67,7 @@ RepackWorkerMain(Datum main_arg) LogicalDecodingContext *decoding_ctx; SharedFileSet *sfs; Snapshot snapshot; + char buf[32]; am_repack_worker = true; @@ -111,6 +113,23 @@ RepackWorkerMain(Datum main_arg) BGWORKER_BYPASS_ALLOWCONN | BGWORKER_BYPASS_ROLELOGINCHECK); + /* + * Adopt the backend's timeouts. We run in a new session as the table + * owner, so role- and database-level settings would otherwise apply here, + * and the user running REPACK could neither see nor override them. + * + * lock_timeout is armed by any lock wait (the snapshot builder's wait for + * older transactions is one), and transaction_timeout by + * StartTransaction(); our transaction spans the whole command. + * statement_timeout and idle_in_transaction_session_timeout need no + * handling: only the command loop in PostgresMain() arms them, and a + * background worker never runs it. + */ + snprintf(buf, sizeof(buf), "%d", shared->lock_timeout); + SetConfigOption("lock_timeout", buf, PGC_SUSET, PGC_S_OVERRIDE); + snprintf(buf, sizeof(buf), "%d", shared->transaction_timeout); + SetConfigOption("transaction_timeout", buf, PGC_SUSET, PGC_S_OVERRIDE); + /* * Transaction is needed to open relation, and it also provides us with a * resource owner. diff --git a/src/include/commands/repack_internal.h b/src/include/commands/repack_internal.h index 42111aa4ae3..6b4906fd750 100644 --- a/src/include/commands/repack_internal.h +++ b/src/include/commands/repack_internal.h @@ -106,6 +106,10 @@ typedef struct DecodingWorkerShared pid_t backend_pid; ProcNumber backend_proc_number; + /* Timeouts in effect in the backend. See RepackWorkerMain(). */ + int lock_timeout; + int transaction_timeout; + /* * Memory the queue is located in. * -- 2.37.1 (Apple Git-137.1)