v0011-0002-Renamed-the-flag-to-BGWORKER_PROTECTED.patch
application/octet-stream
Filename: v0011-0002-Renamed-the-flag-to-BGWORKER_PROTECTED.patch
Type: application/octet-stream
Part: 1
From bc41ea1629f9e16f1c92c3475befecb0f6ef9a8c Mon Sep 17 00:00:00 2001
From: "iwata.aya" <iwata.aya@fujitsu.com>
Date: Thu, 25 Dec 2025 17:16:55 +0900
Subject: [PATCH v0011 2/2] Renamed the flag to BGWORKER_PROTECTED and set
default behavior to Terminate.
---
doc/src/sgml/bgworker.sgml | 6 +-
src/backend/postmaster/bgworker.c | 2 +-
src/backend/storage/ipc/procarray.c | 2 +-
src/include/postmaster/bgworker.h | 2 +-
.../worker_spi/t/002_worker_terminate.pl | 117 ++++++++++++------
src/test/modules/worker_spi/worker_spi.c | 6 +-
6 files changed, 90 insertions(+), 45 deletions(-)
diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml
index a7c238750fc..f56a1850ffb 100644
--- a/doc/src/sgml/bgworker.sgml
+++ b/doc/src/sgml/bgworker.sgml
@@ -109,11 +109,11 @@ typedef struct BackgroundWorker
</varlistentry>
<varlistentry>
- <term><literal>BGWORKER_INTERRUPTABLE</literal></term>
+ <term><literal>BGWORKER_PROTECTED</literal></term>
<listitem>
<para>
- <indexterm><primary>BGWORKER_INTERRUPTABLE</primary></indexterm>
- Requests termination of the background worker when its connected database is
+ <indexterm><primary>BGWORKER_PROTECTED</primary></indexterm>
+ Prevents termination of the background worker when its connected database is
dropped, renamed, moved to a different tablespace, or used as a template for
<command>CREATE DATABASE</command>. Specifically, the postmaster sends a
termination signal when any of these commands affect the worker's database:
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 8334b75548c..4e0aa195140 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -1421,7 +1421,7 @@ TerminateInterruptableBgWorkersByDbOid(Oid databaseId)
BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
if (slot->in_use &&
- (slot->worker.bgw_flags & BGWORKER_INTERRUPTABLE))
+ !(slot->worker.bgw_flags & BGWORKER_PROTECTED))
{
PGPROC *proc = BackendPidGetProc(slot->pid);
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index de80422caea..68b6aff151f 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -3780,7 +3780,7 @@ CountOtherDBBackends(Oid databaseId, int *nbackends, int *nprepared)
/*
* Terminate all background workers for this database, if they had
- * requested it (BGWORKER_INTERRUPTABLE)
+ * requested it (BGWORKER_PROTECTED)
*/
TerminateInterruptableBgWorkersByDbOid(databaseId);
diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h
index e43881448d5..022b8130a64 100644
--- a/src/include/postmaster/bgworker.h
+++ b/src/include/postmaster/bgworker.h
@@ -64,7 +64,7 @@
* database command.
* Requires BGWORKER_SHMEM_ACCESS and BGWORKER_BACKEND_DATABASE_CONNECTION.
*/
-#define BGWORKER_INTERRUPTABLE 0x0004
+#define BGWORKER_PROTECTED 0x0004
/*
* This class is used internally for parallel queries, to keep track of the
diff --git a/src/test/modules/worker_spi/t/002_worker_terminate.pl b/src/test/modules/worker_spi/t/002_worker_terminate.pl
index 5467e423fd9..ca59f3a836b 100644
--- a/src/test/modules/worker_spi/t/002_worker_terminate.pl
+++ b/src/test/modules/worker_spi/t/002_worker_terminate.pl
@@ -50,6 +50,21 @@ sub run_db_command
note("background worker can be terminated at $testname");
}
+# Confirm a background worker is still running
+sub confirm_bgworker_running
+{
+ my ($node, $dbname, $testinfo) = @_;
+
+ my $result = $node->safe_psql(
+ "$dbname", qq(
+ SELECT count(1) FROM pg_stat_activity
+ WHERE backend_type = 'worker_spi dynamic';));
+
+ is($result, '1',
+ "background worker is not stopped after $testinfo");
+
+}
+
my $node = PostgreSQL::Test::Cluster->new('mynode');
$node->init;
$node->start;
@@ -64,10 +79,15 @@ if (!$node->check_extension('injection_points'))
$node->safe_psql('postgres', 'CREATE EXTENSION worker_spi;');
-# Launch a background worker without BGWORKER_INTERRUPTABLE
+# Launch a background worker without BGWORKER_PROTECTED
launch_bgworker($node, 'postgres', 0, "false");
-# Ensure CREATE DATABASE WITH TEMPLATE fails because background worker retains
+# Ensure CREATE DATABASE WITH TEMPLATE sucseeds because background worker retains
+
+run_db_command(
+ $node,
+ "CREATE DATABASE testdb WITH TEMPLATE postgres",
+ "CREATE DATABASE WITH TEMPLATE");
# The injection point 'reduce-ncounts' reduces the number of backend
# retries, allowing for shorter test runs. See CountOtherDBBackends().
@@ -77,22 +97,20 @@ $node->safe_psql('postgres',
my $stderr;
+# Ensure BGWORKER_PROTECTED allows background workers not to be
+# terminated at some database manipulations.
+#
+# Testcase 1: CREATE DATABASE WITH TEMPLATE
+launch_bgworker($node, 'postgres', 1, "true");
$node->psql(
'postgres',
- "CREATE DATABASE testdb WITH TEMPLATE postgres",
+ "CREATE DATABASE testdb2 WITH TEMPLATE postgres",
stderr => \$stderr);
ok( $stderr =~
- "source database \"postgres\" is being accessed by other users",
+ "source database \"postgres\" is being accessed by other users",
"background worker blocked the database creation");
-# Confirm a background worker is still running
-my $result = $node->safe_psql(
- "postgres", qq(
- SELECT count(1) FROM pg_stat_activity
- WHERE backend_type = 'worker_spi dynamic';));
-
-is($result, '1',
- "background worker is still running after CREATE DATABASE WITH TEMPLATE");
+confirm_bgworker_running($node, "postgres", "CREATE DATABASE WITH TEMPLATE");
# Terminate the worker for upcoming tests
$node->safe_psql(
@@ -100,26 +118,23 @@ $node->safe_psql(
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity WHERE backend_type = 'worker_spi dynamic';));
-# The injection point won't be used anymore, release it.
-$node->safe_psql('postgres',
- "SELECT injection_points_detach('reduce-ncounts');");
-
-# Ensure BGWORKER_INTERRUPTABLE allows background workers to be
-# terminated at some database manipulations.
-#
-# Testcase 1: CREATE DATABASE WITH TEMPLATE
-launch_bgworker($node, 'postgres', 1, "true");
-run_db_command(
- $node,
- "CREATE DATABASE testdb WITH TEMPLATE postgres",
- "CREATE DATABASE WITH TEMPLATE");
-
# Testcase 2: ALTER DATABASE RENAME
launch_bgworker($node, 'testdb', 2, "true");
-run_db_command(
- $node,
+$node->psql(
+ 'testdb',
"ALTER DATABASE testdb RENAME TO renameddb",
- "ALTER DATABASE RENAME");
+ stderr => \$stderr);
+ok( $stderr =~
+ "current database cannot be renamed",
+ "background worker blocked the alter database rename to");
+
+confirm_bgworker_running($node, "testdb", "ALTER DATABASE RENAME TO");
+
+# Terminate the worker for upcoming tests
+$node->safe_psql(
+ "testdb", qq(
+ SELECT pg_terminate_backend(pid)
+ FROM pg_stat_activity WHERE backend_type = 'worker_spi dynamic';));
# Preparation for the next test; create another tablespace
my $tablespace = PostgreSQL::Test::Utils::tempdir;
@@ -127,14 +142,44 @@ $node->safe_psql('postgres',
"CREATE TABLESPACE test_tablespace LOCATION '$tablespace'");
# Testcase 3: ALTER DATABASE SET TABLESPACE
-launch_bgworker($node, 'renameddb', 3, "true");
-run_db_command(
- $node,
- "ALTER DATABASE renameddb SET TABLESPACE test_tablespace",
- "ALTER DATABASE SET TABLESPACE");
+launch_bgworker($node, 'testdb', 3, "true");
+$node->psql(
+ 'testdb',
+ "ALTER DATABASE testdb SET TABLESPACE test_tablespace",
+ stderr => \$stderr);
+ok( $stderr =~
+ "cannot change the tablespace of the currently open database",
+ "background worker blocked the alter database set tablespace");
+
+confirm_bgworker_running($node, "testdb", "ALTER DATABASE SET TABLESPACE");
+
+# Terminate the worker for upcoming tests
+$node->safe_psql(
+ "testdb", qq(
+ SELECT pg_terminate_backend(pid)
+ FROM pg_stat_activity WHERE backend_type = 'worker_spi dynamic';));
# Testcase 4: DROP DATABASE
-launch_bgworker($node, 'renameddb', 4, "true");
-run_db_command($node, "DROP DATABASE renameddb", "DROP DATABASE");
+launch_bgworker($node, 'testdb', 4, "true");
+$node->psql(
+ 'testdb',
+ "DROP DATABASE testdb",
+ stderr => \$stderr);
+ok( $stderr =~
+ "cannot drop the currently open database",
+ "background worker blocked the database drop");
+
+confirm_bgworker_running($node, "testdb", "DROP DATABASE");
+
+# Terminate the worker
+$node->safe_psql(
+ "testdb", qq(
+ SELECT pg_terminate_backend(pid)
+ FROM pg_stat_activity WHERE backend_type = 'worker_spi dynamic';));
+
+
+# The injection point won't be used anymore, release it.
+$node->safe_psql('postgres',
+ "SELECT injection_points_detach('reduce-ncounts');");
done_testing();
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 50d16aaf9a8..04ef060ff42 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -404,14 +404,14 @@ worker_spi_launch(PG_FUNCTION_ARGS)
Size ndim;
int nelems;
Datum *datum_flags;
- bool request_termination = PG_GETARG_BOOL(4);
+ bool prevent_termination = PG_GETARG_BOOL(4);
memset(&worker, 0, sizeof(worker));
worker.bgw_flags = BGWORKER_SHMEM_ACCESS |
BGWORKER_BACKEND_DATABASE_CONNECTION;
- if (request_termination)
- worker.bgw_flags |= BGWORKER_INTERRUPTABLE;
+ if (prevent_termination)
+ worker.bgw_flags |= BGWORKER_PROTECTED;
worker.bgw_start_time = BgWorkerStart_RecoveryFinished;
worker.bgw_restart_time = BGW_NEVER_RESTART;
--
2.39.3