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