* system out of backup mode, thus making it a lot more safe to call from
* an error handler.
*
+ * The caller can pass 'arg' as 'true' or 'false' to control whether a warning
+ * is emitted.
+ *
* NB: This is only for aborting a non-exclusive backup that doesn't write
* backup_label. A backup started with pg_start_backup() needs to be finished
* with pg_stop_backup().
+ *
+ * NB: This gets used as a before_shmem_exit handler, hence the odd-looking
+ * signature.
*/
void
-do_pg_abort_backup(void)
+do_pg_abort_backup(int code, Datum arg)
{
+ bool emit_warning = DatumGetBool(arg);
+
/*
* Quick exit if session is not keeping around a non-exclusive backup
* already started.
*/
- if (sessionBackupState == SESSION_BACKUP_NONE)
+ if (sessionBackupState != SESSION_BACKUP_NON_EXCLUSIVE)
return;
WALInsertLockAcquireExclusive();
Assert(XLogCtl->Insert.nonExclusiveBackups > 0);
- Assert(sessionBackupState == SESSION_BACKUP_NON_EXCLUSIVE);
XLogCtl->Insert.nonExclusiveBackups--;
if (XLogCtl->Insert.exclusiveBackupState == EXCLUSIVE_BACKUP_NONE &&
XLogCtl->Insert.forcePageWrites = false;
}
WALInsertLockRelease();
+
+ if (emit_warning)
+ ereport(WARNING,
+ (errmsg("aborting backup due to backend exiting before pg_stop_back up was called")));
+}
+
+/*
+ * Register a handler that will warn about unterminated backups at end of
+ * session, unless this has already been done.
+ */
+void
+register_persistent_abort_backup_handler(void)
+{
+ static bool already_done = false;
+
+ if (already_done)
+ return;
+ before_shmem_exit(do_pg_abort_backup, DatumGetBool(true));
+ already_done = true;
}
/*
static StringInfo label_file;
static StringInfo tblspc_map_file;
-/*
- * Called when the backend exits with a running non-exclusive base backup,
- * to clean up state.
- */
-static void
-nonexclusive_base_backup_cleanup(int code, Datum arg)
-{
- do_pg_abort_backup();
- ereport(WARNING,
- (errmsg("aborting backup due to backend exiting before pg_stop_backup was called")));
-}
-
/*
* pg_start_backup: set up for taking an on-line backup dump
*
tblspc_map_file = makeStringInfo();
MemoryContextSwitchTo(oldcontext);
+ register_persistent_abort_backup_handler();
+
startpoint = do_pg_start_backup(backupidstr, fast, NULL, label_file,
NULL, tblspc_map_file, false, true);
-
- before_shmem_exit(nonexclusive_base_backup_cleanup, (Datum) 0);
}
PG_RETURN_LSN(startpoint);
* and tablespace map so they can be written to disk by the caller.
*/
stoppoint = do_pg_stop_backup(label_file->data, waitforarchive, NULL);
- cancel_before_shmem_exit(nonexclusive_base_backup_cleanup, (Datum) 0);
values[1] = CStringGetTextDatum(label_file->data);
values[2] = CStringGetTextDatum(tblspc_map_file->data);
bool sizeonly);
static void send_int8_string(StringInfoData *buf, int64 intval);
static void SendBackupHeader(List *tablespaces);
-static void base_backup_cleanup(int code, Datum arg);
static void perform_base_backup(basebackup_options *opt);
static void parse_basebackup_options(List *options, basebackup_options *opt);
static void SendXlogRecPtrResult(XLogRecPtr ptr, TimeLineID tli);
NULL,
};
-
-/*
- * Called when ERROR or FATAL happens in perform_base_backup() after
- * we have started the backup - make sure we end it!
- */
-static void
-base_backup_cleanup(int code, Datum arg)
-{
- do_pg_abort_backup();
-}
-
/*
* Actually do a base backup for the specified tablespaces.
*
* do_pg_stop_backup() should be inside the error cleanup block!
*/
- PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
+ PG_ENSURE_ERROR_CLEANUP(do_pg_abort_backup, BoolGetDatum(false));
{
ListCell *lc;
tablespaceinfo *ti;
endptr = do_pg_stop_backup(labelfile->data, !opt->nowait, &endtli);
}
- PG_END_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0);
+ PG_END_ENSURE_ERROR_CLEANUP(do_pg_abort_backup, BoolGetDatum(false));
if (opt->includewal)
bool needtblspcmapfile);
extern XLogRecPtr do_pg_stop_backup(char *labelfile, bool waitforarchive,
TimeLineID *stoptli_p);
-extern void do_pg_abort_backup(void);
+extern void do_pg_abort_backup(int code, Datum arg);
+extern void register_persistent_abort_backup_handler(void);
extern SessionBackupState get_backup_status(void);
/* File path names (all relative to $PGDATA) */