diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index cc0350e6d6..006c3153db 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -800,7 +800,8 @@ apw_start_master_worker(void)
worker.bgw_start_time = BgWorkerStart_ConsistentState;
strcpy(worker.bgw_library_name, "pg_prewarm");
strcpy(worker.bgw_function_name, "autoprewarm_main");
- strcpy(worker.bgw_name, "autoprewarm");
+ strcpy(worker.bgw_name, "autoprewarm master");
+ strcpy(worker.bgw_type, "autoprewarm master");
if (process_shared_preload_libraries_in_progress)
{
@@ -840,7 +841,8 @@ apw_start_database_worker(void)
worker.bgw_start_time = BgWorkerStart_ConsistentState;
strcpy(worker.bgw_library_name, "pg_prewarm");
strcpy(worker.bgw_function_name, "autoprewarm_database_main");
- strcpy(worker.bgw_name, "autoprewarm");
+ strcpy(worker.bgw_name, "autoprewarm worker");
+ strcpy(worker.bgw_type, "autoprewarm worker");
/* must set notify PID to wait for shutdown */
worker.bgw_notify_pid = MyProcPid;
diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml
index b422323081..ea1b5c0c8e 100644
--- a/doc/src/sgml/bgworker.sgml
+++ b/doc/src/sgml/bgworker.sgml
@@ -51,6 +51,7 @@ typedef void (*bgworker_main_type)(Datum main_arg);
typedef struct BackgroundWorker
{
char bgw_name[BGW_MAXLEN];
+ char bgw_type[BGW_MAXLEN];
int bgw_flags;
BgWorkerStartTime bgw_start_time;
int bgw_restart_time; /* in seconds, or BGW_NEVER_RESTART */
@@ -64,8 +65,14 @@ typedef struct BackgroundWorker
- bgw_name> is a string to be used in log messages, process
- listings and similar contexts.
+ bgw_name> and bgw_type are
+ strings to be used in log messages, process listings and similar contexts.
+ bgw_type should be the same for all background
+ workers of the same type, so that it is possible to group such workers in a
+ process listing, for example. bgw_name on the
+ other hand can contain additional information about the specific process.
+ (Typically, the string for bgw_name will contain
+ the type somehow, but that is not strictly required.)
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index 13c8ba3b19..c6f7b7af0e 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -467,6 +467,7 @@ LaunchParallelWorkers(ParallelContext *pcxt)
memset(&worker, 0, sizeof(worker));
snprintf(worker.bgw_name, BGW_MAXLEN, "parallel worker for PID %d",
MyProcPid);
+ snprintf(worker.bgw_type, BGW_MAXLEN, "parallel worker");
worker.bgw_flags =
BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION
| BGWORKER_CLASS_PARALLEL;
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 28af6f0f07..4a3c4b4cc9 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -344,6 +344,8 @@ BackgroundWorkerStateChange(void)
*/
ascii_safe_strlcpy(rw->rw_worker.bgw_name,
slot->worker.bgw_name, BGW_MAXLEN);
+ ascii_safe_strlcpy(rw->rw_worker.bgw_type,
+ slot->worker.bgw_type, BGW_MAXLEN);
ascii_safe_strlcpy(rw->rw_worker.bgw_library_name,
slot->worker.bgw_library_name, BGW_MAXLEN);
ascii_safe_strlcpy(rw->rw_worker.bgw_function_name,
@@ -630,6 +632,12 @@ SanityCheckBackgroundWorker(BackgroundWorker *worker, int elevel)
return false;
}
+ /*
+ * If bgw_type is not filled in, use bgw_name.
+ */
+ if (strcmp(worker->bgw_type, "") == 0)
+ strcpy(worker->bgw_type, worker->bgw_name);
+
return true;
}
@@ -671,7 +679,7 @@ bgworker_die(SIGNAL_ARGS)
ereport(FATAL,
(errcode(ERRCODE_ADMIN_SHUTDOWN),
errmsg("terminating background worker \"%s\" due to administrator command",
- MyBgworkerEntry->bgw_name)));
+ MyBgworkerEntry->bgw_type)));
}
/*
@@ -700,7 +708,6 @@ void
StartBackgroundWorker(void)
{
sigjmp_buf local_sigjmp_buf;
- char buf[MAXPGPATH];
BackgroundWorker *worker = MyBgworkerEntry;
bgworker_main_type entrypt;
@@ -710,8 +717,7 @@ StartBackgroundWorker(void)
IsBackgroundWorker = true;
/* Identify myself via ps */
- snprintf(buf, MAXPGPATH, "bgworker: %s", worker->bgw_name);
- init_ps_display(buf, "", "", "");
+ init_ps_display(worker->bgw_name, "", "", "");
/*
* If we're not supposed to have shared memory access, then detach from
@@ -1233,3 +1239,40 @@ LookupBackgroundWorkerFunction(const char *libraryname, const char *funcname)
return (bgworker_main_type)
load_external_function(libraryname, funcname, true, NULL);
}
+
+/*
+ * Given a PID, get the bgw_type of the background worker. Returns NULL if
+ * not a valid background worker.
+ *
+ * The return value is in static memory belonging to this function, so it has
+ * to be used before calling this function again. This is so that the caller
+ * doesn't have to worry about the background worker locking protocol.
+ */
+const char *
+GetBackgroundWorkerTypeByPid(pid_t pid)
+{
+ int slotno;
+ bool found = false;
+ static char result[BGW_MAXLEN];
+
+ LWLockAcquire(BackgroundWorkerLock, LW_SHARED);
+
+ for (slotno = 0; slotno < BackgroundWorkerData->total_slots; slotno++)
+ {
+ BackgroundWorkerSlot *slot = &BackgroundWorkerData->slot[slotno];
+
+ if (slot->pid > 0 && slot->pid == pid)
+ {
+ strcpy(result, slot->worker.bgw_type);
+ found = true;
+ break;
+ }
+ }
+
+ LWLockRelease(BackgroundWorkerLock);
+
+ if (!found)
+ return NULL;
+
+ return result;
+}
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 1bcbce537a..8a2cc2fc2b 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -3117,8 +3117,9 @@ CleanupBackgroundWorker(int pid,
exitstatus = 0;
#endif
- snprintf(namebuf, MAXPGPATH, "%s: %s", _("worker process"),
- rw->rw_worker.bgw_name);
+ snprintf(namebuf, MAXPGPATH, _("background worker \"%s\""),
+ rw->rw_worker.bgw_type);
+
if (!EXIT_STATUS_0(exitstatus))
{
diff --git a/src/backend/replication/logical/launcher.c b/src/backend/replication/logical/launcher.c
index 44bdcab3b9..a613ef4757 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -422,6 +422,7 @@ retry:
else
snprintf(bgw.bgw_name, BGW_MAXLEN,
"logical replication worker for subscription %u", subid);
+ snprintf(bgw.bgw_type, BGW_MAXLEN, "logical replication worker");
bgw.bgw_restart_time = BGW_NEVER_RESTART;
bgw.bgw_notify_pid = MyProcPid;
@@ -775,6 +776,8 @@ ApplyLauncherRegister(void)
snprintf(bgw.bgw_function_name, BGW_MAXLEN, "ApplyLauncherMain");
snprintf(bgw.bgw_name, BGW_MAXLEN,
"logical replication launcher");
+ snprintf(bgw.bgw_type, BGW_MAXLEN,
+ "logical replication launcher");
bgw.bgw_restart_time = 5;
bgw.bgw_notify_pid = 0;
bgw.bgw_main_arg = (Datum) 0;
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 5a968e3758..8d9e7c10ae 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -21,6 +21,7 @@
#include "funcapi.h"
#include "miscadmin.h"
#include "pgstat.h"
+#include "postmaster/bgworker_internals.h"
#include "postmaster/postmaster.h"
#include "storage/proc.h"
#include "storage/procarray.h"
@@ -823,8 +824,19 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
}
}
/* Add backend type */
- values[17] =
- CStringGetTextDatum(pgstat_get_backend_desc(beentry->st_backendType));
+ if (beentry->st_backendType == B_BG_WORKER)
+ {
+ const char *bgw_type;
+
+ bgw_type = GetBackgroundWorkerTypeByPid(beentry->st_procpid);
+ if (bgw_type)
+ values[17] = CStringGetTextDatum(bgw_type);
+ else
+ nulls[17] = true;
+ }
+ else
+ values[17] =
+ CStringGetTextDatum(pgstat_get_backend_desc(beentry->st_backendType));
}
else
{
diff --git a/src/include/postmaster/bgworker.h b/src/include/postmaster/bgworker.h
index e2ecd3c9eb..6b4e631880 100644
--- a/src/include/postmaster/bgworker.h
+++ b/src/include/postmaster/bgworker.h
@@ -88,6 +88,7 @@ typedef enum
typedef struct BackgroundWorker
{
char bgw_name[BGW_MAXLEN];
+ char bgw_type[BGW_MAXLEN];
int bgw_flags;
BgWorkerStartTime bgw_start_time;
int bgw_restart_time; /* in seconds, or BGW_NEVER_RESTART */
@@ -122,6 +123,7 @@ extern BgwHandleStatus GetBackgroundWorkerPid(BackgroundWorkerHandle *handle,
extern BgwHandleStatus WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pid);
extern BgwHandleStatus
WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *);
+extern const char *GetBackgroundWorkerTypeByPid(pid_t pid);
/* Terminate a bgworker */
extern void TerminateBackgroundWorker(BackgroundWorkerHandle *handle);
diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c
index 3ae9018360..561f6f9bac 100644
--- a/src/test/modules/test_shm_mq/setup.c
+++ b/src/test/modules/test_shm_mq/setup.c
@@ -219,7 +219,7 @@ setup_background_workers(int nworkers, dsm_segment *seg)
worker.bgw_restart_time = BGW_NEVER_RESTART;
sprintf(worker.bgw_library_name, "test_shm_mq");
sprintf(worker.bgw_function_name, "test_shm_mq_main");
- snprintf(worker.bgw_name, BGW_MAXLEN, "test_shm_mq");
+ snprintf(worker.bgw_type, BGW_MAXLEN, "test_shm_mq");
worker.bgw_main_arg = UInt32GetDatum(dsm_segment_handle(seg));
/* set bgw_notify_pid, so we can detect if the worker stops */
worker.bgw_notify_pid = MyProcPid;
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 12c8cd5774..4c6ab6d575 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -111,7 +111,7 @@ initialize_worker_spi(worktable *table)
StartTransactionCommand();
SPI_connect();
PushActiveSnapshot(GetTransactionSnapshot());
- pgstat_report_activity(STATE_RUNNING, "initializing spi_worker schema");
+ pgstat_report_activity(STATE_RUNNING, "initializing worker_spi schema");
/* XXX could we use CREATE SCHEMA IF NOT EXISTS? */
initStringInfo(&buf);
@@ -359,7 +359,8 @@ _PG_init(void)
*/
for (i = 1; i <= worker_spi_total_workers; i++)
{
- snprintf(worker.bgw_name, BGW_MAXLEN, "worker %d", i);
+ snprintf(worker.bgw_name, BGW_MAXLEN, "worker_spi worker %d", i);
+ snprintf(worker.bgw_type, BGW_MAXLEN, "worker_spi");
worker.bgw_main_arg = Int32GetDatum(i);
RegisterBackgroundWorker(&worker);
@@ -385,7 +386,8 @@ worker_spi_launch(PG_FUNCTION_ARGS)
worker.bgw_restart_time = BGW_NEVER_RESTART;
sprintf(worker.bgw_library_name, "worker_spi");
sprintf(worker.bgw_function_name, "worker_spi_main");
- snprintf(worker.bgw_name, BGW_MAXLEN, "worker %d", i);
+ snprintf(worker.bgw_name, BGW_MAXLEN, "worker_spi worker %d", i);
+ snprintf(worker.bgw_type, BGW_MAXLEN, "worker_spi");
worker.bgw_main_arg = Int32GetDatum(i);
/* set bgw_notify_pid so that we can use WaitForBackgroundWorkerStartup */
worker.bgw_notify_pid = MyProcPid;