Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+45-49
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)