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

Commit f701368

Browse files
committed
Fix minor problems with non-exclusive backup cleanup.
The previous coding imagined that it could call before_shmem_exit() when a non-exclusive backup began and then remove the previously-added handler by calling cancel_before_shmem_exit() when that backup ended. However, this only works provided that nothing else in the system has registered a before_shmem_exit() hook in the interim, because cancel_before_shmem_exit() is documented to remove a callback only if it is the latest callback registered. It also only works if nothing can ERROR out between the time that sessionBackupState is reset and the time that cancel_before_shmem_exit(), which doesn't seem to be strictly true. To fix, leave the handler installed for the lifetime of the session, arrange to install it just once, and teach it to quietly do nothing if there isn't a non-exclusive backup in process. This was originally committed to master as 3036401, but I did not back-patch at the time because the consequences were minor. However, now there's been a second report of this causing trouble with a slightly different test case than the one I reported originally, so now I'm back-patching as far as v11 where JIT was introduced. Patch by me, reviewed by Kyotaro Horiguchi, Michael Paquier (who preferred a different approach, but got outvoted), Fujii Masao, and Tom Lane, and with comments by various others. New problem report from Bharath Rupireddy. Discussion: http://postgr.es/m/CA+TgmobMjnyBfNhGTKQEDbqXYE3_rXWpc4CM63fhyerNCes3mA@mail.gmail.com Discussion: http://postgr.es/m/CALj2ACWk7j4F2v2fxxYfrroOF=AdFNPr1WsV+AGtHAFQOqm_pw@mail.gmail.com
1 parent b144edb commit f701368

File tree

4 files changed

+35
-33
lines changed

4 files changed

+35
-33
lines changed

src/backend/access/transam/xlog.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11329,23 +11329,30 @@ do_pg_stop_backup(char *labelfile, bool waitforarchive, TimeLineID *stoptli_p)
1132911329
* system out of backup mode, thus making it a lot more safe to call from
1133011330
* an error handler.
1133111331
*
11332+
* The caller can pass 'arg' as 'true' or 'false' to control whether a warning
11333+
* is emitted.
11334+
*
1133211335
* NB: This is only for aborting a non-exclusive backup that doesn't write
1133311336
* backup_label. A backup started with pg_start_backup() needs to be finished
1133411337
* with pg_stop_backup().
11338+
*
11339+
* NB: This gets used as a before_shmem_exit handler, hence the odd-looking
11340+
* signature.
1133511341
*/
1133611342
void
11337-
do_pg_abort_backup(void)
11343+
do_pg_abort_backup(int code, Datum arg)
1133811344
{
11345+
bool emit_warning = DatumGetBool(arg);
11346+
1133911347
/*
1134011348
* Quick exit if session is not keeping around a non-exclusive backup
1134111349
* already started.
1134211350
*/
11343-
if (sessionBackupState == SESSION_BACKUP_NONE)
11351+
if (sessionBackupState != SESSION_BACKUP_NON_EXCLUSIVE)
1134411352
return;
1134511353

1134611354
WALInsertLockAcquireExclusive();
1134711355
Assert(XLogCtl->Insert.nonExclusiveBackups > 0);
11348-
Assert(sessionBackupState == SESSION_BACKUP_NON_EXCLUSIVE);
1134911356
XLogCtl->Insert.nonExclusiveBackups--;
1135011357

1135111358
if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
@@ -11354,6 +11361,25 @@ do_pg_abort_backup(void)
1135411361
XLogCtl->Insert.forcePageWrites = false;
1135511362
}
1135611363
WALInsertLockRelease();
11364+
11365+
if (emit_warning)
11366+
ereport(WARNING,
11367+
(errmsg("aborting backup due to backend exiting before pg_stop_back up was called")));
11368+
}
11369+
11370+
/*
11371+
* Register a handler that will warn about unterminated backups at end of
11372+
* session, unless this has already been done.
11373+
*/
11374+
void
11375+
register_persistent_abort_backup_handler(void)
11376+
{
11377+
static bool already_done = false;
11378+
11379+
if (already_done)
11380+
return;
11381+
before_shmem_exit(do_pg_abort_backup, DatumGetBool(true));
11382+
already_done = true;
1135711383
}
1135811384

1135911385
/*

src/backend/access/transam/xlogfuncs.c

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,6 @@
4242
static StringInfo label_file;
4343
static StringInfo tblspc_map_file;
4444

45-
/*
46-
* Called when the backend exits with a running non-exclusive base backup,
47-
* to clean up state.
48-
*/
49-
static void
50-
nonexclusive_base_backup_cleanup(int code, Datum arg)
51-
{
52-
do_pg_abort_backup();
53-
ereport(WARNING,
54-
(errmsg("aborting backup due to backend exiting before pg_stop_backup was called")));
55-
}
56-
5745
/*
5846
* pg_start_backup: set up for taking an on-line backup dump
5947
*
@@ -101,10 +89,10 @@ pg_start_backup(PG_FUNCTION_ARGS)
10189
tblspc_map_file = makeStringInfo();
10290
MemoryContextSwitchTo(oldcontext);
10391

92+
register_persistent_abort_backup_handler();
93+
10494
startpoint = do_pg_start_backup(backupidstr, fast, NULL, label_file,
10595
NULL, tblspc_map_file, false, true);
106-
107-
before_shmem_exit(nonexclusive_base_backup_cleanup, (Datum) 0);
10896
}
10997

11098
PG_RETURN_LSN(startpoint);
@@ -246,7 +234,6 @@ pg_stop_backup_v2(PG_FUNCTION_ARGS)
246234
* and tablespace map so they can be written to disk by the caller.
247235
*/
248236
stoppoint = do_pg_stop_backup(label_file->data, waitforarchive, NULL);
249-
cancel_before_shmem_exit(nonexclusive_base_backup_cleanup, (Datum) 0);
250237

251238
values[1] = CStringGetTextDatum(label_file->data);
252239
values[2] = CStringGetTextDatum(tblspc_map_file->data);

src/backend/replication/basebackup.c

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ static int64 _tarWriteDir(const char *pathbuf, int basepathlen, struct stat *sta
6666
bool sizeonly);
6767
static void send_int8_string(StringInfoData *buf, int64 intval);
6868
static void SendBackupHeader(List *tablespaces);
69-
static void base_backup_cleanup(int code, Datum arg);
7069
static void perform_base_backup(basebackup_options *opt);
7170
static void parse_basebackup_options(List *options, basebackup_options *opt);
7271
static void SendXlogRecPtrResult(XLogRecPtr ptr, TimeLineID tli);
@@ -231,17 +230,6 @@ static const struct exclude_list_item noChecksumFiles[] = {
231230
{NULL, false}
232231
};
233232

234-
235-
/*
236-
* Called when ERROR or FATAL happens in perform_base_backup() after
237-
* we have started the backup - make sure we end it!
238-
*/
239-
static void
240-
base_backup_cleanup(int code, Datum arg)
241-
{
242-
do_pg_abort_backup();
243-
}
244-
245233
/*
246234
* Actually do a base backup for the specified tablespaces.
247235
*
@@ -280,7 +268,7 @@ perform_base_backup(basebackup_options *opt)
280268
* do_pg_stop_backup() should be inside the error cleanup block!
281269
*/
282270

283-
PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
271+
PG_ENSURE_ERROR_CLEANUP(do_pg_abort_backup, BoolGetDatum(false));
284272
{
285273
ListCell *lc;
286274
tablespaceinfo *ti;
@@ -389,7 +377,7 @@ perform_base_backup(basebackup_options *opt)
389377

390378
endptr = do_pg_stop_backup(labelfile->data, !opt->nowait, &endtli);
391379
}
392-
PG_END_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
380+
PG_END_ENSURE_ERROR_CLEANUP(do_pg_abort_backup, BoolGetDatum(false));
393381

394382

395383
if (opt->includewal)

src/include/access/xlog.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,8 @@ extern XLogRecPtr do_pg_start_backup(const char *backupidstr, bool fast,
326326
bool needtblspcmapfile);
327327
extern XLogRecPtr do_pg_stop_backup(char *labelfile, bool waitforarchive,
328328
TimeLineID *stoptli_p);
329-
extern void do_pg_abort_backup(void);
329+
extern void do_pg_abort_backup(int code, Datum arg);
330+
extern void register_persistent_abort_backup_handler(void);
330331
extern SessionBackupState get_backup_status(void);
331332

332333
/* File path names (all relative to $PGDATA) */

0 commit comments

Comments
 (0)