Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c7bba5e

Browse files
committed
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.
1 parent f80cf69 commit c7bba5e

File tree

1 file changed

+42
-13
lines changed

1 file changed

+42
-13
lines changed

src/backend/postmaster/pgstat.c

+42-13
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
1515
*
16-
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.103 2005/08/08 03:11:40 tgl Exp $
16+
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.104 2005/08/09 21:14:55 tgl Exp $
1717
* ----------
1818
*/
1919
#include "postgres.h"
@@ -46,6 +46,7 @@
4646
#include "storage/ipc.h"
4747
#include "storage/pg_shmem.h"
4848
#include "storage/pmsignal.h"
49+
#include "storage/procarray.h"
4950
#include "tcop/tcopprot.h"
5051
#include "utils/hsearch.h"
5152
#include "utils/memutils.h"
@@ -1605,8 +1606,8 @@ PgstatCollectorMain(int argc, char *argv[])
16051606
/*
16061607
* Create the known backends table
16071608
*/
1608-
pgStatBeTable = (PgStat_StatBeEntry *) palloc0(
1609-
sizeof(PgStat_StatBeEntry) * MaxBackends);
1609+
pgStatBeTable = (PgStat_StatBeEntry *)
1610+
palloc0(sizeof(PgStat_StatBeEntry) * MaxBackends);
16101611

16111612
readPipe = pgStatPipe[0];
16121613

@@ -2456,13 +2457,15 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
24562457
PgStat_StatDBEntry dbbuf;
24572458
PgStat_StatTabEntry *tabentry;
24582459
PgStat_StatTabEntry tabbuf;
2460+
PgStat_StatBeEntry *beentry;
24592461
HASHCTL hash_ctl;
24602462
HTAB *tabhash = NULL;
24612463
FILE *fpin;
24622464
int32 format_id;
24632465
int maxbackends = 0;
24642466
int havebackends = 0;
24652467
bool found;
2468+
bool check_pids;
24662469
MemoryContext use_mcxt;
24672470
int mcxt_flags;
24682471

@@ -2472,16 +2475,22 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
24722475
* TopTransactionContext instead, so the caller must only know the last
24732476
* XactId when this call happened to know if his tables are still valid or
24742477
* already gone!
2478+
*
2479+
* Also, if running in a regular backend, we check backend entries against
2480+
* the PGPROC array so that we can detect stale entries. This lets us
2481+
* discard entries whose BETERM message got lost for some reason.
24752482
*/
24762483
if (pgStatRunningInCollector || IsAutoVacuumProcess())
24772484
{
24782485
use_mcxt = NULL;
24792486
mcxt_flags = 0;
2487+
check_pids = false;
24802488
}
24812489
else
24822490
{
24832491
use_mcxt = TopTransactionContext;
24842492
mcxt_flags = HASH_CONTEXT;
2493+
check_pids = true;
24852494
}
24862495

24872496
/*
@@ -2665,32 +2674,52 @@ pgstat_read_statsfile(HTAB **dbhash, Oid onlydb,
26652674
if (betab == NULL || numbackends == NULL || *betab == NULL)
26662675
goto done;
26672676

2677+
if (havebackends >= maxbackends)
2678+
goto done;
2679+
26682680
/*
26692681
* Read it directly into the table.
26702682
*/
2671-
if (fread(&(*betab)[havebackends], 1,
2672-
sizeof(PgStat_StatBeEntry), fpin) !=
2683+
beentry = &(*betab)[havebackends];
2684+
2685+
if (fread(beentry, 1, sizeof(PgStat_StatBeEntry), fpin) !=
26732686
sizeof(PgStat_StatBeEntry))
26742687
{
26752688
ereport(pgStatRunningInCollector ? LOG : WARNING,
26762689
(errmsg("corrupted pgstat.stat file")));
26772690
goto done;
26782691
}
26792692

2693+
/*
2694+
* If possible, check PID to verify still running
2695+
*/
2696+
if (check_pids && !IsBackendPid(beentry->procpid))
2697+
{
2698+
/*
2699+
* Note: we could send a BETERM message to tell the
2700+
* collector to drop the entry, but I'm a bit worried
2701+
* about race conditions. For now, just silently ignore
2702+
* dead entries; they'll get recycled eventually anyway.
2703+
*/
2704+
2705+
/* Don't accept the entry */
2706+
memset(beentry, 0, sizeof(PgStat_StatBeEntry));
2707+
break;
2708+
}
2709+
26802710
/*
26812711
* Count backends per database here.
26822712
*/
2683-
dbentry = (PgStat_StatDBEntry *) hash_search(*dbhash,
2684-
(void *) &((*betab)[havebackends].databaseid),
2685-
HASH_FIND, NULL);
2713+
dbentry = (PgStat_StatDBEntry *)
2714+
hash_search(*dbhash,
2715+
&(beentry->databaseid),
2716+
HASH_FIND,
2717+
NULL);
26862718
if (dbentry)
26872719
dbentry->n_backends++;
26882720

26892721
havebackends++;
2690-
if (numbackends != 0)
2691-
*numbackends = havebackends;
2692-
if (havebackends >= maxbackends)
2693-
goto done;
2722+
*numbackends = havebackends;
26942723

26952724
break;
26962725

@@ -2728,10 +2757,10 @@ backend_read_statsfile(void)
27282757
{
27292758
if (IsAutoVacuumProcess())
27302759
{
2731-
Assert(!pgStatRunningInCollector);
27322760
/* already read it? */
27332761
if (pgStatDBHash)
27342762
return;
2763+
Assert(!pgStatRunningInCollector);
27352764
pgstat_read_statsfile(&pgStatDBHash, InvalidOid,
27362765
&pgStatBeTable, &pgStatNumBackends);
27372766
}

0 commit comments

Comments
 (0)