summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-08-09 21:14:55 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-08-09 21:14:55 +0000
commitc7bba5e21c25e5b4afda3df7c1a9ef9d7a4584ed (patch)
treea66b7c4e8308eb141b341872ef85656cc52bf8ac
parentf80cf69031fae2b46d262bad02f67489d47f17a4 (diff)
Make backends that are reading the pgstats file verify each backend PID
against the PGPROC array. Anything in the file that isn't in PGPROC gets rejected as being a stale entry. This should solve complaints about stale entries in pg_stat_activity after a BETERM message has been dropped due to overload.
-rw-r--r--src/backend/postmaster/pgstat.c55
1 files changed, 42 insertions, 13 deletions
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 9a07915f79b..00ed7b837da 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -13,7 +13,7 @@
*
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.103 2005/08/08 03:11:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.104 2005/08/09 21:14:55 tgl Exp $
* ----------
*/
#include "postgres.h"
@@ -46,6 +46,7 @@
#include "storage/ipc.h"
#include "storage/pg_shmem.h"
#include "storage/pmsignal.h"
+#include "storage/procarray.h"
#include "tcop/tcopprot.h"
#include "utils/hsearch.h"
#include "utils/memutils.h"
@@ -1605,8 +1606,8 @@ PgstatCollectorMain(int argc, char *argv[])
/*
* Create the known backends table
*/
- pgStatBeTable = (PgStat_StatBeEntry *) palloc0(
- sizeof(PgStat_StatBeEntry) * MaxBackends);
+ pgStatBeTable = (PgStat_StatBeEntry *)
+ palloc0(sizeof(PgStat_StatBeEntry) * MaxBackends);
readPipe = pgStatPipe[0];
@@ -2456,6 +2457,7 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
PgStat_StatDBEntry dbbuf;
PgStat_StatTabEntry *tabentry;
PgStat_StatTabEntry tabbuf;
+ PgStat_StatBeEntry *beentry;
HASHCTL hash_ctl;
HTAB *tabhash = NULL;
FILE *fpin;
@@ -2463,6 +2465,7 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
int maxbackends = 0;
int havebackends = 0;
bool found;
+ bool check_pids;
MemoryContext use_mcxt;
int mcxt_flags;
@@ -2472,16 +2475,22 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
* TopTransactionContext instead, so the caller must only know the last
* XactId when this call happened to know if his tables are still valid or
* already gone!
+ *
+ * Also, if running in a regular backend, we check backend entries against
+ * the PGPROC array so that we can detect stale entries. This lets us
+ * discard entries whose BETERM message got lost for some reason.
*/
if (pgStatRunningInCollector || IsAutoVacuumProcess())
{
use_mcxt = NULL;
mcxt_flags = 0;
+ check_pids = false;
}
else
{
use_mcxt = TopTransactionContext;
mcxt_flags = HASH_CONTEXT;
+ check_pids = true;
}
/*
@@ -2665,11 +2674,15 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
if (betab == NULL || numbackends == NULL || *betab == NULL)
goto done;
+ if (havebackends >= maxbackends)
+ goto done;
+
/*
* Read it directly into the table.
*/
- if (fread(&(*betab)[havebackends], 1,
- sizeof(PgStat_StatBeEntry), fpin) !=
+ beentry = &(*betab)[havebackends];
+
+ if (fread(beentry, 1, sizeof(PgStat_StatBeEntry), fpin) !=
sizeof(PgStat_StatBeEntry))
{
ereport(pgStatRunningInCollector ? LOG : WARNING,
@@ -2678,19 +2691,35 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
}
/*
+ * If possible, check PID to verify still running
+ */
+ if (check_pids && !IsBackendPid(beentry->procpid))
+ {
+ /*
+ * Note: we could send a BETERM message to tell the
+ * collector to drop the entry, but I'm a bit worried
+ * about race conditions. For now, just silently ignore
+ * dead entries; they'll get recycled eventually anyway.
+ */
+
+ /* Don't accept the entry */
+ memset(beentry, 0, sizeof(PgStat_StatBeEntry));
+ break;
+ }
+
+ /*
* Count backends per database here.
*/
- dbentry = (PgStat_StatDBEntry *) hash_search(*dbhash,
- (void *) &((*betab)[havebackends].databaseid),
- HASH_FIND, NULL);
+ dbentry = (PgStat_StatDBEntry *)
+ hash_search(*dbhash,
+ &(beentry->databaseid),
+ HASH_FIND,
+ NULL);
if (dbentry)
dbentry->n_backends++;
havebackends++;
- if (numbackends != 0)
- *numbackends = havebackends;
- if (havebackends >= maxbackends)
- goto done;
+ *numbackends = havebackends;
break;
@@ -2728,10 +2757,10 @@ backend_read_statsfile(void)
{
if (IsAutoVacuumProcess())
{
- Assert(!pgStatRunningInCollector);
/* already read it? */
if (pgStatDBHash)
return;
+ Assert(!pgStatRunningInCollector);
pgstat_read_statsfile(&pgStatDBHash, InvalidOid,
&pgStatBeTable, &pgStatNumBackends);
}