Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * pg_backup_utils.c 4 : * Utility routines shared by pg_dump and pg_restore 5 : * 6 : * 7 : * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group 8 : * Portions Copyright (c) 1994, Regents of the University of California 9 : * 10 : * src/bin/pg_dump/pg_backup_utils.c 11 : * 12 : *------------------------------------------------------------------------- 13 : */ 14 : #include "postgres_fe.h" 15 : 16 : #include "parallel.h" 17 : #include "pg_backup_utils.h" 18 : 19 : /* Globals exported by this file */ 20 : const char *progname = NULL; 21 : 22 : #define MAX_ON_EXIT_NICELY 20 23 : 24 : static struct 25 : { 26 : on_exit_nicely_callback function; 27 : void *arg; 28 : } on_exit_nicely_list[MAX_ON_EXIT_NICELY]; 29 : 30 : static int on_exit_nicely_index; 31 : 32 : /* 33 : * Parse a --section=foo command line argument. 34 : * 35 : * Set or update the bitmask in *dumpSections according to arg. 36 : * dumpSections is initialised as DUMP_UNSECTIONED by pg_dump and 37 : * pg_restore so they can know if this has even been called. 38 : */ 39 : void 40 12 : set_dump_section(const char *arg, int *dumpSections) 41 : { 42 : /* if this is the first call, clear all the bits */ 43 12 : if (*dumpSections == DUMP_UNSECTIONED) 44 12 : *dumpSections = 0; 45 : 46 12 : if (strcmp(arg, "pre-data") == 0) 47 4 : *dumpSections |= DUMP_PRE_DATA; 48 8 : else if (strcmp(arg, "data") == 0) 49 4 : *dumpSections |= DUMP_DATA; 50 4 : else if (strcmp(arg, "post-data") == 0) 51 4 : *dumpSections |= DUMP_POST_DATA; 52 : else 53 : { 54 0 : pg_log_error("unrecognized section name: \"%s\"", arg); 55 0 : pg_log_error_hint("Try \"%s --help\" for more information.", progname); 56 0 : exit_nicely(1); 57 : } 58 12 : } 59 : 60 : 61 : /* Register a callback to be run when exit_nicely is invoked. */ 62 : void 63 422 : on_exit_nicely(on_exit_nicely_callback function, void *arg) 64 : { 65 422 : if (on_exit_nicely_index >= MAX_ON_EXIT_NICELY) 66 0 : pg_fatal("out of on_exit_nicely slots"); 67 422 : on_exit_nicely_list[on_exit_nicely_index].function = function; 68 422 : on_exit_nicely_list[on_exit_nicely_index].arg = arg; 69 422 : on_exit_nicely_index++; 70 422 : } 71 : 72 : /* 73 : * Run accumulated on_exit_nicely callbacks in reverse order and then exit 74 : * without printing any message. 75 : * 76 : * If running in a parallel worker thread on Windows, we only exit the thread, 77 : * not the whole process. 78 : * 79 : * Note that in parallel operation on Windows, the callback(s) will be run 80 : * by each thread since the list state is necessarily shared by all threads; 81 : * each callback must contain logic to ensure it does only what's appropriate 82 : * for its thread. On Unix, callbacks are also run by each process, but only 83 : * for callbacks established before we fork off the child processes. (It'd 84 : * be cleaner to reset the list after fork(), and let each child establish 85 : * its own callbacks; but then the behavior would be completely inconsistent 86 : * between Windows and Unix. For now, just be sure to establish callbacks 87 : * before forking to avoid inconsistency.) 88 : */ 89 : void 90 532 : exit_nicely(int code) 91 : { 92 : int i; 93 : 94 874 : for (i = on_exit_nicely_index - 1; i >= 0; i--) 95 342 : on_exit_nicely_list[i].function(code, 96 : on_exit_nicely_list[i].arg); 97 : 98 : #ifdef WIN32 99 : if (parallel_init_done && GetCurrentThreadId() != mainThreadId) 100 : _endthreadex(code); 101 : #endif 102 : 103 532 : exit(code); 104 : }