Here is a proposed solution that splits bgw_name into bgw_type and
bgw_name_extra.  bgw_type shows up in pg_stat_activity.backend_type.
Uses of application_name are removed, because they are no longer
necessary to identity the process type.

This code appears to be buggy because I sometimes get NULL results of
the backend_type lookup, implying that it couldn't find the background
worker slot.  This needs another look.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From 45444b3362e8d00e998fae195023b8a55d96a005 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pete...@gmx.net>
Date: Tue, 30 May 2017 22:59:19 -0400
Subject: [PATCH] Split background worker name into type and name

Remove background worker structure field bgw_name and add two new fields
bgw_type and bgw_name_extra.  The bgw_type field is intended to be set
to the same value for all workers of the same type, so they can be
grouped in pg_stat_activity, for example.  The bgw_name_extra field can
be any suffix that is specific to the individual worker.  So bgw_type +
bgw_name_extra is the old bgw_name.

The backend_type column in pg_stat_activity now shows bgw_type for a
background worker.  The ps listing and some log messages no longer call
out that a process is a "background worker" but just show the bgw_type.
That way, being a background worker is effectively an implementation
detail now that is not shown to the user.

Don't set application_name in logical replication launcher or worker
anymore.  Those processes can now be identified using the mechanisms
described above instead.
---
 doc/src/sgml/bgworker.sgml                 | 17 +++++++++---
 src/backend/access/transam/parallel.c      |  3 ++-
 src/backend/postmaster/bgworker.c          | 42 ++++++++++++++++--------------
 src/backend/postmaster/postmaster.c        | 16 +++++-------
 src/backend/replication/logical/launcher.c | 15 +++++------
 src/backend/replication/logical/worker.c   |  4 ---
 src/backend/utils/adt/pgstatfuncs.c        | 29 +++++++++++++++++++--
 src/include/postmaster/bgworker.h          |  3 ++-
 src/test/modules/test_shm_mq/setup.c       |  2 +-
 src/test/modules/worker_spi/worker_spi.c   | 17 +++++++-----
 10 files changed, 92 insertions(+), 56 deletions(-)

diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml
index b422323081..0a89a5044b 100644
--- a/doc/src/sgml/bgworker.sgml
+++ b/doc/src/sgml/bgworker.sgml
@@ -50,7 +50,8 @@ <title>Background Worker Processes</title>
 typedef void (*bgworker_main_type)(Datum main_arg);
 typedef struct BackgroundWorker
 {
-    char        bgw_name[BGW_MAXLEN];
+    char        bgw_type[BGW_MAXLEN];
+    char        bgw_name_extra[BGW_MAXLEN];
     int         bgw_flags;
     BgWorkerStartTime bgw_start_time;
     int         bgw_restart_time;       /* in seconds, or BGW_NEVER_RESTART */
@@ -64,8 +65,18 @@ <title>Background Worker Processes</title>
   </para>
 
   <para>
-   <structfield>bgw_name</> is a string to be used in log messages, process
-   listings and similar contexts.
+   <structfield>bgw_type</> is a string to be used in log messages, process
+   listings and similar contexts.  It 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.
+  </para>
+
+  <para>
+   <structfield>bgw_name_extra</> is a string that is appended
+   to <structfield>bgw_type</structfield> in some contexts such as process
+   listings.  Unlike <structfield>bgw_type</structfield>, it can contain
+   information that is particular to this process.  The string, if not empty,
+   should normally start with a space or other separator.
   </para>
 
   <para>
diff --git a/src/backend/access/transam/parallel.c 
b/src/backend/access/transam/parallel.c
index 2dad3e8a65..fbdcf2da31 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -436,7 +436,8 @@ LaunchParallelWorkers(ParallelContext *pcxt)
 
        /* Configure a worker. */
        memset(&worker, 0, sizeof(worker));
-       snprintf(worker.bgw_name, BGW_MAXLEN, "parallel worker for PID %d",
+       snprintf(worker.bgw_type, BGW_MAXLEN, "parallel worker");
+       snprintf(worker.bgw_name_extra, BGW_MAXLEN, " for PID %d",
                         MyProcPid);
        worker.bgw_flags =
                BGWORKER_SHMEM_ACCESS | BGWORKER_BACKEND_DATABASE_CONNECTION
diff --git a/src/backend/postmaster/bgworker.c 
b/src/backend/postmaster/bgworker.c
index c3454276bf..65318a5fb8 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -342,8 +342,10 @@ BackgroundWorkerStateChange(void)
                 * Copy strings in a paranoid way.  If shared memory is 
corrupted, the
                 * source data might not even be NUL-terminated.
                 */
-               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_name_extra,
+                                                  slot->worker.bgw_name_extra, 
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,
@@ -389,9 +391,10 @@ BackgroundWorkerStateChange(void)
                rw->rw_terminate = false;
 
                /* Log it! */
-               ereport(DEBUG1,
-                               (errmsg("registering background worker \"%s\"",
-                                               rw->rw_worker.bgw_name)));
+               elog(DEBUG1,
+                        "registering background worker \"%s%s\"",
+                        rw->rw_worker.bgw_type,
+                        rw->rw_worker.bgw_name_extra);
 
                slist_push_head(&BackgroundWorkerList, &rw->rw_lnode);
        }
@@ -421,9 +424,10 @@ ForgetBackgroundWorker(slist_mutable_iter *cur)
 
        slot->in_use = false;
 
-       ereport(DEBUG1,
-                       (errmsg("unregistering background worker \"%s\"",
-                                       rw->rw_worker.bgw_name)));
+       elog(DEBUG1,
+                "unregistering background worker \"%s%s\"",
+                rw->rw_worker.bgw_type,
+                rw->rw_worker.bgw_name_extra);
 
        slist_delete_current(cur);
        free(rw);
@@ -588,7 +592,7 @@ SanityCheckBackgroundWorker(BackgroundWorker *worker, int 
elevel)
                        ereport(elevel,
                                        
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                         errmsg("background worker \"%s\": must 
attach to shared memory in order to request a database connection",
-                                                       worker->bgw_name)));
+                                                       worker->bgw_type)));
                        return false;
                }
 
@@ -597,7 +601,7 @@ SanityCheckBackgroundWorker(BackgroundWorker *worker, int 
elevel)
                        ereport(elevel,
                                        
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                         errmsg("background worker \"%s\": 
cannot request database access if starting at postmaster start",
-                                                       worker->bgw_name)));
+                                                       worker->bgw_type)));
                        return false;
                }
 
@@ -611,7 +615,7 @@ SanityCheckBackgroundWorker(BackgroundWorker *worker, int 
elevel)
                ereport(elevel,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 errmsg("background worker \"%s\": invalid 
restart interval",
-                                               worker->bgw_name)));
+                                               worker->bgw_type)));
                return false;
        }
 
@@ -626,7 +630,7 @@ SanityCheckBackgroundWorker(BackgroundWorker *worker, int 
elevel)
                ereport(elevel,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 errmsg("background worker \"%s\": parallel 
workers may not be configured for restart",
-                                               worker->bgw_name)));
+                                               worker->bgw_type)));
                return false;
        }
 
@@ -670,8 +674,8 @@ bgworker_die(SIGNAL_ARGS)
 
        ereport(FATAL,
                        (errcode(ERRCODE_ADMIN_SHUTDOWN),
-                        errmsg("terminating background worker \"%s\" due to 
administrator command",
-                                       MyBgworkerEntry->bgw_name)));
+                        errmsg("terminating %s due to administrator command",
+                                       MyBgworkerEntry->bgw_type)));
 }
 
 /*
@@ -710,7 +714,7 @@ StartBackgroundWorker(void)
        IsBackgroundWorker = true;
 
        /* Identify myself via ps */
-       snprintf(buf, MAXPGPATH, "bgworker: %s", worker->bgw_name);
+       snprintf(buf, MAXPGPATH, "%s%s", worker->bgw_type, 
worker->bgw_name_extra);
        init_ps_display(buf, "", "", "");
 
        /*
@@ -852,8 +856,8 @@ RegisterBackgroundWorker(BackgroundWorker *worker)
        static int      numworkers = 0;
 
        if (!IsUnderPostmaster)
-               ereport(DEBUG1,
-                (errmsg("registering background worker \"%s\"", 
worker->bgw_name)));
+               elog(DEBUG1,
+                        "registering background worker \"%s%s\"", 
worker->bgw_type, worker->bgw_name_extra);
 
        if (!process_shared_preload_libraries_in_progress &&
                strcmp(worker->bgw_library_name, "postgres") != 0)
@@ -862,7 +866,7 @@ RegisterBackgroundWorker(BackgroundWorker *worker)
                        ereport(LOG,
                                        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                         errmsg("background worker \"%s\": must 
be registered in shared_preload_libraries",
-                                                       worker->bgw_name)));
+                                                       worker->bgw_type)));
                return;
        }
 
@@ -874,7 +878,7 @@ RegisterBackgroundWorker(BackgroundWorker *worker)
                ereport(LOG,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 errmsg("background worker \"%s\": only dynamic 
background workers can request notification",
-                                               worker->bgw_name)));
+                                               worker->bgw_type)));
                return;
        }
 
diff --git a/src/backend/postmaster/postmaster.c 
b/src/backend/postmaster/postmaster.c
index 35b4ec88d3..991caeace7 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -3070,7 +3070,6 @@ static bool
 CleanupBackgroundWorker(int pid,
                                                int exitstatus) /* child's exit 
status */
 {
-       char            namebuf[MAXPGPATH];
        slist_mutable_iter iter;
 
        slist_foreach_modify(iter, &BackgroundWorkerList)
@@ -3088,9 +3087,6 @@ CleanupBackgroundWorker(int pid,
                        exitstatus = 0;
 #endif
 
-               snprintf(namebuf, MAXPGPATH, "%s: %s", _("worker process"),
-                                rw->rw_worker.bgw_name);
-
                if (!EXIT_STATUS_0(exitstatus))
                {
                        /* Record timestamp, so we know when to restart the 
worker. */
@@ -3112,7 +3108,7 @@ CleanupBackgroundWorker(int pid,
                {
                        if (!EXIT_STATUS_0(exitstatus) && 
!EXIT_STATUS_1(exitstatus))
                        {
-                               HandleChildCrash(pid, exitstatus, namebuf);
+                               HandleChildCrash(pid, exitstatus, 
rw->rw_worker.bgw_type);
                                return true;
                        }
                }
@@ -3125,7 +3121,7 @@ CleanupBackgroundWorker(int pid,
                if (!ReleasePostmasterChildSlot(rw->rw_child_slot) &&
                        (rw->rw_worker.bgw_flags & BGWORKER_SHMEM_ACCESS) != 0)
                {
-                       HandleChildCrash(pid, exitstatus, namebuf);
+                       HandleChildCrash(pid, exitstatus, 
rw->rw_worker.bgw_type);
                        return true;
                }
 
@@ -3150,7 +3146,7 @@ CleanupBackgroundWorker(int pid,
                ReportBackgroundWorkerExit(&iter);              /* report child 
death */
 
                LogChildExit(EXIT_STATUS_0(exitstatus) ? DEBUG1 : LOG,
-                                        namebuf, pid, exitstatus);
+                                        rw->rw_worker.bgw_type, pid, 
exitstatus);
 
                return true;
        }
@@ -5576,9 +5572,9 @@ do_start_bgworker(RegisteredBgWorker *rw)
                return false;
        }
 
-       ereport(DEBUG1,
-                       (errmsg("starting background worker process \"%s\"",
-                                       rw->rw_worker.bgw_name)));
+       elog(DEBUG1,
+                "starting background worker process \"%s%s\"",
+                rw->rw_worker.bgw_type, rw->rw_worker.bgw_name_extra);
 
 #ifdef EXEC_BACKEND
        switch ((worker_pid = bgworker_forkexec(rw->rw_shmem_slot)))
diff --git a/src/backend/replication/logical/launcher.c 
b/src/backend/replication/logical/launcher.c
index b956052014..624d8e9ca7 100644
--- a/src/backend/replication/logical/launcher.c
+++ b/src/backend/replication/logical/launcher.c
@@ -379,12 +379,13 @@ logicalrep_worker_launch(Oid dbid, Oid subid, const char 
*subname, Oid userid,
        bgw.bgw_start_time = BgWorkerStart_RecoveryFinished;
        snprintf(bgw.bgw_library_name, BGW_MAXLEN, "postgres");
        snprintf(bgw.bgw_function_name, BGW_MAXLEN, "ApplyWorkerMain");
+       snprintf(bgw.bgw_type, BGW_MAXLEN, "logical replication worker");
        if (OidIsValid(relid))
-               snprintf(bgw.bgw_name, BGW_MAXLEN,
-                                "logical replication worker for subscription 
%u sync %u", subid, relid);
+               snprintf(bgw.bgw_name_extra, BGW_MAXLEN,
+                                " for subscription %u sync %u", subid, relid);
        else
-               snprintf(bgw.bgw_name, BGW_MAXLEN,
-                                "logical replication worker for subscription 
%u", subid);
+               snprintf(bgw.bgw_name_extra, BGW_MAXLEN,
+                                " for subscription %u", subid);
 
        bgw.bgw_restart_time = BGW_NEVER_RESTART;
        bgw.bgw_notify_pid = MyProcPid;
@@ -706,7 +707,7 @@ ApplyLauncherRegister(void)
        bgw.bgw_start_time = BgWorkerStart_RecoveryFinished;
        snprintf(bgw.bgw_library_name, BGW_MAXLEN, "postgres");
        snprintf(bgw.bgw_function_name, BGW_MAXLEN, "ApplyLauncherMain");
-       snprintf(bgw.bgw_name, BGW_MAXLEN,
+       snprintf(bgw.bgw_type, BGW_MAXLEN,
                         "logical replication launcher");
        bgw.bgw_restart_time = 5;
        bgw.bgw_notify_pid = 0;
@@ -797,10 +798,6 @@ ApplyLauncherMain(Datum main_arg)
        pqsignal(SIGTERM, logicalrep_worker_sigterm);
        BackgroundWorkerUnblockSignals();
 
-       /* Make it easy to identify our processes. */
-       SetConfigOption("application_name", MyBgworkerEntry->bgw_name,
-                                       PGC_USERSET, PGC_S_SESSION);
-
        LogicalRepCtx->launcher_pid = MyProcPid;
 
        /*
diff --git a/src/backend/replication/logical/worker.c 
b/src/backend/replication/logical/worker.c
index c67720bd2f..e59b9db407 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -1467,10 +1467,6 @@ ApplyWorkerMain(Datum main_arg)
        MyLogicalRepWorker->last_send_time = MyLogicalRepWorker->last_recv_time 
=
                MyLogicalRepWorker->reply_time = GetCurrentTimestamp();
 
-       /* Make it easy to identify our processes. */
-       SetConfigOption("application_name", MyBgworkerEntry->bgw_name,
-                                       PGC_USERSET, PGC_S_SESSION);
-
        /* Load the libpq-specific functions */
        load_file("libpqwalreceiver", false);
 
diff --git a/src/backend/utils/adt/pgstatfuncs.c 
b/src/backend/utils/adt/pgstatfuncs.c
index e0cae1ba1e..9d779491b5 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"
@@ -820,8 +821,32 @@ 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)
+                       {
+                               slist_iter      siter;
+                               bool            found = false;
+
+                               slist_foreach(siter, &BackgroundWorkerList)
+                               {
+                                       RegisteredBgWorker *rw;
+
+                                       rw = 
slist_container(RegisteredBgWorker, rw_lnode, siter.cur);
+
+                                       if (rw->rw_pid == beentry->st_procpid)
+                                       {
+                                               values[17] =
+                                                       
CStringGetTextDatum(rw->rw_worker.bgw_type);
+                                               found = true;
+                                               break;
+                                       }
+                               }
+
+                               if (!found)
+                                       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 51a5978ea8..daf7a3f7fe 100644
--- a/src/include/postmaster/bgworker.h
+++ b/src/include/postmaster/bgworker.h
@@ -87,7 +87,8 @@ typedef enum
 
 typedef struct BackgroundWorker
 {
-       char            bgw_name[BGW_MAXLEN];
+       char            bgw_type[BGW_MAXLEN];
+       char            bgw_name_extra[BGW_MAXLEN];
        int                     bgw_flags;
        BgWorkerStartTime bgw_start_time;
        int                     bgw_restart_time;               /* in seconds, 
or BGW_NEVER_RESTART */
diff --git a/src/test/modules/test_shm_mq/setup.c 
b/src/test/modules/test_shm_mq/setup.c
index 06c49bdb40..54c8dea4ed 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 9abfc714a9..9c217b69c8 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -181,8 +181,10 @@ worker_spi_main(Datum main_arg)
        /* Connect to our database */
        BackgroundWorkerInitializeConnection("postgres", NULL);
 
-       elog(LOG, "%s initialized with %s.%s",
-                MyBgworkerEntry->bgw_name, table->schema, table->name);
+       elog(LOG, "%s%s initialized with %s.%s",
+                MyBgworkerEntry->bgw_type,
+                MyBgworkerEntry->bgw_name_extra,
+                table->schema, table->name);
        initialize_worker_spi(table);
 
        /*
@@ -282,8 +284,9 @@ worker_spi_main(Datum main_arg)
                                                                                
          SPI_tuptable->tupdesc,
                                                                                
          1, &isnull));
                        if (!isnull)
-                               elog(LOG, "%s: count in %s.%s is now %d",
-                                        MyBgworkerEntry->bgw_name,
+                               elog(LOG, "%s%s: count in %s.%s is now %d",
+                                        MyBgworkerEntry->bgw_type,
+                                        MyBgworkerEntry->bgw_name_extra,
                                         table->schema, table->name, val);
                }
 
@@ -357,7 +360,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_type, BGW_MAXLEN, "worker_spi worker");
+               snprintf(worker.bgw_name_extra, BGW_MAXLEN, " %d", i);
                worker.bgw_main_arg = Int32GetDatum(i);
 
                RegisterBackgroundWorker(&worker);
@@ -383,7 +387,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_type, BGW_MAXLEN, "worker_spi worker");
+       snprintf(worker.bgw_name_extra, BGW_MAXLEN, " %d", i);
        worker.bgw_main_arg = Int32GetDatum(i);
        /* set bgw_notify_pid so that we can use WaitForBackgroundWorkerStartup 
*/
        worker.bgw_notify_pid = MyProcPid;
-- 
2.13.0

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to