Skip to content

Commit 46c5a21

Browse files
committed
Avoid crashing when a table is deleted while we're on the process of checking
it. Per report from Tom Lane based on buildfarm evidence.
1 parent a41f73a commit 46c5a21

File tree

1 file changed

+45
-49
lines changed

1 file changed

+45
-49
lines changed

src/backend/postmaster/autovacuum.c

Lines changed: 45 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
*
5656
*
5757
* IDENTIFICATION
58-
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.80 2008/07/01 02:09:34 tgl Exp $
58+
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.81 2008/07/17 21:02:31 alvherre Exp $
5959
*
6060
*-------------------------------------------------------------------------
6161
*/
@@ -176,6 +176,9 @@ typedef struct autovac_table
176176
int at_vacuum_cost_delay;
177177
int at_vacuum_cost_limit;
178178
bool at_wraparound;
179+
char *at_relname;
180+
char *at_nspname;
181+
char *at_datname;
179182
} autovac_table;
180183

181184
/*-------------
@@ -282,15 +285,13 @@ static void relation_needs_vacanalyze(Oid relid, Form_pg_autovacuum avForm,
282285
PgStat_StatTabEntry *tabentry, bool *dovacuum,
283286
bool *doanalyze, bool *wraparound);
284287

285-
static void autovacuum_do_vac_analyze(Oid relid, bool dovacuum,
286-
bool doanalyze, int freeze_min_age,
287-
bool for_wraparound,
288+
static void autovacuum_do_vac_analyze(autovac_table *tab,
288289
BufferAccessStrategy bstrategy);
289290
static HeapTuple get_pg_autovacuum_tuple_relid(Relation avRel, Oid relid);
290291
static PgStat_StatTabEntry *get_pgstat_tabentry_relid(Oid relid, bool isshared,
291292
PgStat_StatDBEntry *shared,
292293
PgStat_StatDBEntry *dbentry);
293-
static void autovac_report_activity(VacuumStmt *vacstmt, Oid relid);
294+
static void autovac_report_activity(autovac_table *tab);
294295
static void avl_sighup_handler(SIGNAL_ARGS);
295296
static void avl_sigusr1_handler(SIGNAL_ARGS);
296297
static void avl_sigterm_handler(SIGNAL_ARGS);
@@ -2061,9 +2062,6 @@ do_autovacuum(void)
20612062
autovac_table *tab;
20622063
WorkerInfo worker;
20632064
bool skipit;
2064-
char *datname,
2065-
*nspname,
2066-
*relname;
20672065

20682066
CHECK_FOR_INTERRUPTS();
20692067

@@ -2158,13 +2156,17 @@ do_autovacuum(void)
21582156

21592157
/*
21602158
* Save the relation name for a possible error message, to avoid a
2161-
* catalog lookup in case of an error. Note: they must live in a
2162-
* long-lived memory context because we call vacuum and analyze in
2163-
* different transactions.
2159+
* catalog lookup in case of an error. If any of these return NULL,
2160+
* then the relation has been dropped since last we checked; skip it.
2161+
* Note: they must live in a long-lived memory context because we call
2162+
* vacuum and analyze in different transactions.
21642163
*/
2165-
datname = get_database_name(MyDatabaseId);
2166-
nspname = get_namespace_name(get_rel_namespace(tab->at_relid));
2167-
relname = get_rel_name(tab->at_relid);
2164+
2165+
tab->at_relname = get_rel_name(tab->at_relid);
2166+
tab->at_nspname = get_namespace_name(get_rel_namespace(tab->at_relid));
2167+
tab->at_datname = get_database_name(MyDatabaseId);
2168+
if (!tab->at_relname || !tab->at_nspname || !tab->at_datname)
2169+
goto deleted;
21682170

21692171
/*
21702172
* We will abort vacuuming the current table if something errors out,
@@ -2175,12 +2177,7 @@ do_autovacuum(void)
21752177
{
21762178
/* have at it */
21772179
MemoryContextSwitchTo(TopTransactionContext);
2178-
autovacuum_do_vac_analyze(tab->at_relid,
2179-
tab->at_dovacuum,
2180-
tab->at_doanalyze,
2181-
tab->at_freeze_min_age,
2182-
tab->at_wraparound,
2183-
bstrategy);
2180+
autovacuum_do_vac_analyze(tab, bstrategy);
21842181

21852182
/*
21862183
* Clear a possible query-cancel signal, to avoid a late reaction
@@ -2199,10 +2196,10 @@ do_autovacuum(void)
21992196
HOLD_INTERRUPTS();
22002197
if (tab->at_dovacuum)
22012198
errcontext("automatic vacuum of table \"%s.%s.%s\"",
2202-
datname, nspname, relname);
2199+
tab->at_datname, tab->at_nspname, tab->at_relname);
22032200
else
22042201
errcontext("automatic analyze of table \"%s.%s.%s\"",
2205-
datname, nspname, relname);
2202+
tab->at_datname, tab->at_nspname, tab->at_relname);
22062203
EmitErrorReport();
22072204

22082205
/* this resets the PGPROC flags too */
@@ -2219,10 +2216,14 @@ do_autovacuum(void)
22192216
/* the PGPROC flags are reset at the next end of transaction */
22202217

22212218
/* be tidy */
2219+
deleted:
2220+
if (tab->at_datname != NULL)
2221+
pfree(tab->at_datname);
2222+
if (tab->at_nspname != NULL)
2223+
pfree(tab->at_nspname);
2224+
if (tab->at_relname != NULL)
2225+
pfree(tab->at_relname);
22222226
pfree(tab);
2223-
pfree(datname);
2224-
pfree(nspname);
2225-
pfree(relname);
22262227

22272228
/* remove my info from shared memory */
22282229
LWLockAcquire(AutovacuumLock, LW_EXCLUSIVE);
@@ -2299,6 +2300,8 @@ get_pgstat_tabentry_relid(Oid relid, bool isshared, PgStat_StatDBEntry *shared,
22992300
* Recheck whether a plain table still needs vacuum or analyze; be it because
23002301
* it does directly, or because its TOAST table does. Return value is a valid
23012302
* autovac_table pointer if it does, NULL otherwise.
2303+
*
2304+
* Note that the returned autovac_table does not have the name fields set.
23022305
*/
23032306
static autovac_table *
23042307
table_recheck_autovac(Oid relid)
@@ -2437,6 +2440,9 @@ table_recheck_autovac(Oid relid)
24372440
tab->at_vacuum_cost_limit = vac_cost_limit;
24382441
tab->at_vacuum_cost_delay = vac_cost_delay;
24392442
tab->at_wraparound = wraparound || toast_wraparound;
2443+
tab->at_relname = NULL;
2444+
tab->at_nspname = NULL;
2445+
tab->at_datname = NULL;
24402446
}
24412447

24422448
heap_close(avRel, AccessShareLock);
@@ -2607,8 +2613,7 @@ relation_needs_vacanalyze(Oid relid,
26072613
* Vacuum and/or analyze the specified table
26082614
*/
26092615
static void
2610-
autovacuum_do_vac_analyze(Oid relid, bool dovacuum, bool doanalyze,
2611-
int freeze_min_age, bool for_wraparound,
2616+
autovacuum_do_vac_analyze(autovac_table *tab,
26122617
BufferAccessStrategy bstrategy)
26132618
{
26142619
VacuumStmt vacstmt;
@@ -2617,18 +2622,18 @@ autovacuum_do_vac_analyze(Oid relid, bool dovacuum, bool doanalyze,
26172622
MemSet(&vacstmt, 0, sizeof(vacstmt));
26182623

26192624
vacstmt.type = T_VacuumStmt;
2620-
vacstmt.vacuum = dovacuum;
2625+
vacstmt.vacuum = tab->at_dovacuum;
26212626
vacstmt.full = false;
2622-
vacstmt.analyze = doanalyze;
2623-
vacstmt.freeze_min_age = freeze_min_age;
2627+
vacstmt.analyze = tab->at_doanalyze;
2628+
vacstmt.freeze_min_age = tab->at_freeze_min_age;
26242629
vacstmt.verbose = false;
26252630
vacstmt.relation = NULL; /* not used since we pass a relid */
26262631
vacstmt.va_cols = NIL;
26272632

26282633
/* Let pgstat know what we're doing */
2629-
autovac_report_activity(&vacstmt, relid);
2634+
autovac_report_activity(tab);
26302635

2631-
vacuum(&vacstmt, relid, bstrategy, for_wraparound, true);
2636+
vacuum(&vacstmt, tab->at_relid, bstrategy, tab->at_wraparound, true);
26322637
}
26332638

26342639
/*
@@ -2643,37 +2648,28 @@ autovacuum_do_vac_analyze(Oid relid, bool dovacuum, bool doanalyze,
26432648
* bother to report "<IDLE>" or some such.
26442649
*/
26452650
static void
2646-
autovac_report_activity(VacuumStmt *vacstmt, Oid relid)
2651+
autovac_report_activity(autovac_table *tab)
26472652
{
2648-
char *relname = get_rel_name(relid);
2649-
char *nspname = get_namespace_name(get_rel_namespace(relid));
2650-
26512653
#define MAX_AUTOVAC_ACTIV_LEN (NAMEDATALEN * 2 + 32)
2652-
char activity[MAX_AUTOVAC_ACTIV_LEN];
2654+
char activity[MAX_AUTOVAC_ACTIV_LEN];
2655+
int len;
26532656

26542657
/* Report the command and possible options */
2655-
if (vacstmt->vacuum)
2658+
if (tab->at_dovacuum)
26562659
snprintf(activity, MAX_AUTOVAC_ACTIV_LEN,
26572660
"autovacuum: VACUUM%s",
2658-
vacstmt->analyze ? " ANALYZE" : "");
2661+
tab->at_doanalyze ? " ANALYZE" : "");
26592662
else
26602663
snprintf(activity, MAX_AUTOVAC_ACTIV_LEN,
26612664
"autovacuum: ANALYZE");
26622665

26632666
/*
26642667
* Report the qualified name of the relation.
2665-
*
2666-
* Paranoia is appropriate here in case relation was recently dropped ---
2667-
* the lsyscache routines we just invoked will return NULL rather than
2668-
* failing.
26692668
*/
2670-
if (relname && nspname)
2671-
{
2672-
int len = strlen(activity);
2669+
len = strlen(activity);
26732670

2674-
snprintf(activity + len, MAX_AUTOVAC_ACTIV_LEN - len,
2675-
" %s.%s", nspname, relname);
2676-
}
2671+
snprintf(activity + len, MAX_AUTOVAC_ACTIV_LEN - len,
2672+
" %s.%s", tab->at_nspname, tab->at_relname);
26772673

26782674
/* Set statement_timestamp() to current time for pg_stat_activity */
26792675
SetCurrentStatementStartTimestamp();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy