mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-27 21:52:02 +02:00
29275b1d17
Reported-by: Michael Paquier Discussion: https://postgr.es/m/ZZKTDPxBBMt3C0J9@paquier.xyz Backpatch-through: 12
105 lines
3.0 KiB
C
105 lines
3.0 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* pg_backup_utils.c
|
|
* Utility routines shared by pg_dump and pg_restore
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/bin/pg_dump/pg_backup_utils.c
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#include "postgres_fe.h"
|
|
|
|
#include "parallel.h"
|
|
#include "pg_backup_utils.h"
|
|
|
|
/* Globals exported by this file */
|
|
const char *progname = NULL;
|
|
|
|
#define MAX_ON_EXIT_NICELY 20
|
|
|
|
static struct
|
|
{
|
|
on_exit_nicely_callback function;
|
|
void *arg;
|
|
} on_exit_nicely_list[MAX_ON_EXIT_NICELY];
|
|
|
|
static int on_exit_nicely_index;
|
|
|
|
/*
|
|
* Parse a --section=foo command line argument.
|
|
*
|
|
* Set or update the bitmask in *dumpSections according to arg.
|
|
* dumpSections is initialised as DUMP_UNSECTIONED by pg_dump and
|
|
* pg_restore so they can know if this has even been called.
|
|
*/
|
|
void
|
|
set_dump_section(const char *arg, int *dumpSections)
|
|
{
|
|
/* if this is the first call, clear all the bits */
|
|
if (*dumpSections == DUMP_UNSECTIONED)
|
|
*dumpSections = 0;
|
|
|
|
if (strcmp(arg, "pre-data") == 0)
|
|
*dumpSections |= DUMP_PRE_DATA;
|
|
else if (strcmp(arg, "data") == 0)
|
|
*dumpSections |= DUMP_DATA;
|
|
else if (strcmp(arg, "post-data") == 0)
|
|
*dumpSections |= DUMP_POST_DATA;
|
|
else
|
|
{
|
|
pg_log_error("unrecognized section name: \"%s\"", arg);
|
|
pg_log_error_hint("Try \"%s --help\" for more information.", progname);
|
|
exit_nicely(1);
|
|
}
|
|
}
|
|
|
|
|
|
/* Register a callback to be run when exit_nicely is invoked. */
|
|
void
|
|
on_exit_nicely(on_exit_nicely_callback function, void *arg)
|
|
{
|
|
if (on_exit_nicely_index >= MAX_ON_EXIT_NICELY)
|
|
pg_fatal("out of on_exit_nicely slots");
|
|
on_exit_nicely_list[on_exit_nicely_index].function = function;
|
|
on_exit_nicely_list[on_exit_nicely_index].arg = arg;
|
|
on_exit_nicely_index++;
|
|
}
|
|
|
|
/*
|
|
* Run accumulated on_exit_nicely callbacks in reverse order and then exit
|
|
* without printing any message.
|
|
*
|
|
* If running in a parallel worker thread on Windows, we only exit the thread,
|
|
* not the whole process.
|
|
*
|
|
* Note that in parallel operation on Windows, the callback(s) will be run
|
|
* by each thread since the list state is necessarily shared by all threads;
|
|
* each callback must contain logic to ensure it does only what's appropriate
|
|
* for its thread. On Unix, callbacks are also run by each process, but only
|
|
* for callbacks established before we fork off the child processes. (It'd
|
|
* be cleaner to reset the list after fork(), and let each child establish
|
|
* its own callbacks; but then the behavior would be completely inconsistent
|
|
* between Windows and Unix. For now, just be sure to establish callbacks
|
|
* before forking to avoid inconsistency.)
|
|
*/
|
|
void
|
|
exit_nicely(int code)
|
|
{
|
|
int i;
|
|
|
|
for (i = on_exit_nicely_index - 1; i >= 0; i--)
|
|
on_exit_nicely_list[i].function(code,
|
|
on_exit_nicely_list[i].arg);
|
|
|
|
#ifdef WIN32
|
|
if (parallel_init_done && GetCurrentThreadId() != mainThreadId)
|
|
_endthreadex(code);
|
|
#endif
|
|
|
|
exit(code);
|
|
}
|