postgresql/src/bin/pg_dump/pg_backup_utils.c

109 lines
3.1 KiB
C

/*-------------------------------------------------------------------------
*
* pg_backup_utils.c
* Utility routines shared by pg_dump and pg_restore
*
*
* Portions Copyright (c) 1996-2020, 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);
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
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_log_fatal("out of on_exit_nicely slots");
exit_nicely(1);
}
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);
}