LCOV - code coverage report
Current view: top level - src/backend/main - main.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 86.6 % 119 103
Test Date: 2026-03-07 02:14:59 Functions: 85.7 % 7 6
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * main.c
       4              :  *    Stub main() routine for the postgres executable.
       5              :  *
       6              :  * This does some essential startup tasks for any incarnation of postgres
       7              :  * (postmaster, standalone backend, standalone bootstrap process, or a
       8              :  * separately exec'd child of a postmaster) and then dispatches to the
       9              :  * proper FooMain() routine for the incarnation.
      10              :  *
      11              :  *
      12              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      13              :  * Portions Copyright (c) 1994, Regents of the University of California
      14              :  *
      15              :  *
      16              :  * IDENTIFICATION
      17              :  *    src/backend/main/main.c
      18              :  *
      19              :  *-------------------------------------------------------------------------
      20              :  */
      21              : #include "postgres.h"
      22              : 
      23              : #include <unistd.h>
      24              : 
      25              : #if defined(WIN32)
      26              : #include <crtdbg.h>
      27              : #endif
      28              : 
      29              : #if defined(__NetBSD__)
      30              : #include <sys/param.h>
      31              : #endif
      32              : 
      33              : #include "bootstrap/bootstrap.h"
      34              : #include "common/username.h"
      35              : #include "miscadmin.h"
      36              : #include "postmaster/postmaster.h"
      37              : #include "tcop/tcopprot.h"
      38              : #include "utils/help_config.h"
      39              : #include "utils/memutils.h"
      40              : #include "utils/pg_locale.h"
      41              : #include "utils/ps_status.h"
      42              : 
      43              : 
      44              : const char *progname;
      45              : static bool reached_main = false;
      46              : 
      47              : /* names of special must-be-first options for dispatching to subprograms */
      48              : static const char *const DispatchOptionNames[] =
      49              : {
      50              :     [DISPATCH_CHECK] = "check",
      51              :     [DISPATCH_BOOT] = "boot",
      52              :     [DISPATCH_FORKCHILD] = "forkchild",
      53              :     [DISPATCH_DESCRIBE_CONFIG] = "describe-config",
      54              :     [DISPATCH_SINGLE] = "single",
      55              :     /* DISPATCH_POSTMASTER has no name */
      56              : };
      57              : 
      58              : StaticAssertDecl(lengthof(DispatchOptionNames) == DISPATCH_POSTMASTER,
      59              :                  "array length mismatch");
      60              : 
      61              : static void startup_hacks(const char *progname);
      62              : static void init_locale(const char *categoryname, int category, const char *locale);
      63              : static void help(const char *progname);
      64              : static void check_root(const char *progname);
      65              : 
      66              : 
      67              : /*
      68              :  * Any Postgres server process begins execution here.
      69              :  */
      70              : int
      71         2014 : main(int argc, char *argv[])
      72              : {
      73         2014 :     bool        do_check_root = true;
      74         2014 :     DispatchOption dispatch_option = DISPATCH_POSTMASTER;
      75              : 
      76         2014 :     reached_main = true;
      77              : 
      78              :     /*
      79              :      * If supported on the current platform, set up a handler to be called if
      80              :      * the backend/postmaster crashes with a fatal signal or exception.
      81              :      */
      82              : #if defined(WIN32)
      83              :     pgwin32_install_crashdump_handler();
      84              : #endif
      85              : 
      86         2014 :     progname = get_progname(argv[0]);
      87              : 
      88              :     /*
      89              :      * Platform-specific startup hacks
      90              :      */
      91         2014 :     startup_hacks(progname);
      92              : 
      93              :     /*
      94              :      * Remember the physical location of the initially given argv[] array for
      95              :      * possible use by ps display.  On some platforms, the argv[] storage must
      96              :      * be overwritten in order to set the process title for ps. In such cases
      97              :      * save_ps_display_args makes and returns a new copy of the argv[] array.
      98              :      *
      99              :      * save_ps_display_args may also move the environment strings to make
     100              :      * extra room. Therefore this should be done as early as possible during
     101              :      * startup, to avoid entanglements with code that might save a getenv()
     102              :      * result pointer.
     103              :      */
     104         2014 :     argv = save_ps_display_args(argc, argv);
     105              : 
     106              :     /*
     107              :      * Fire up essential subsystems: error and memory management
     108              :      *
     109              :      * Code after this point is allowed to use elog/ereport, though
     110              :      * localization of messages may not work right away, and messages won't go
     111              :      * anywhere but stderr until GUC settings get loaded.
     112              :      */
     113         2014 :     MyProcPid = getpid();
     114         2014 :     MemoryContextInit();
     115              : 
     116              :     /*
     117              :      * Set reference point for stack-depth checking.  (There's no point in
     118              :      * enabling this before error reporting works.)
     119              :      */
     120         2014 :     (void) set_stack_base();
     121              : 
     122              :     /*
     123              :      * Set up locale information
     124              :      */
     125         2014 :     set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("postgres"));
     126              : 
     127              :     /*
     128              :      * Collation is handled by pg_locale.c, and the behavior is dependent on
     129              :      * the provider. strcoll(), etc., should not be called directly.
     130              :      */
     131         2014 :     init_locale("LC_COLLATE", LC_COLLATE, "C");
     132              : 
     133              :     /*
     134              :      * In the postmaster, absorb the environment value for LC_CTYPE.
     135              :      * Individual backends will change it later to pg_database.datctype, but
     136              :      * the postmaster cannot do that.  If we leave it set to "C" then message
     137              :      * localization might not work well in the postmaster.
     138              :      */
     139         2014 :     init_locale("LC_CTYPE", LC_CTYPE, "");
     140              : 
     141              :     /*
     142              :      * LC_MESSAGES will get set later during GUC option processing, but we set
     143              :      * it here to allow startup error messages to be localized.
     144              :      */
     145              : #ifdef LC_MESSAGES
     146         2014 :     init_locale("LC_MESSAGES", LC_MESSAGES, "");
     147              : #endif
     148              : 
     149              :     /* We keep these set to "C" always.  See pg_locale.c for explanation. */
     150         2014 :     init_locale("LC_MONETARY", LC_MONETARY, "C");
     151         2014 :     init_locale("LC_NUMERIC", LC_NUMERIC, "C");
     152         2014 :     init_locale("LC_TIME", LC_TIME, "C");
     153              : 
     154              :     /*
     155              :      * Now that we have absorbed as much as we wish to from the locale
     156              :      * environment, remove any LC_ALL setting, so that the environment
     157              :      * variables installed by pg_perm_setlocale have force.
     158              :      */
     159         2014 :     unsetenv("LC_ALL");
     160              : 
     161              :     /*
     162              :      * Catch standard options before doing much else, in particular before we
     163              :      * insist on not being root.
     164              :      */
     165         2014 :     if (argc > 1)
     166              :     {
     167         2014 :         if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
     168              :         {
     169            1 :             help(progname);
     170            1 :             exit(0);
     171              :         }
     172         2013 :         if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
     173              :         {
     174          823 :             fputs(PG_BACKEND_VERSIONSTR, stdout);
     175          823 :             exit(0);
     176              :         }
     177              : 
     178              :         /*
     179              :          * In addition to the above, we allow "--describe-config" and "-C var"
     180              :          * to be called by root.  This is reasonably safe since these are
     181              :          * read-only activities.  The -C case is important because pg_ctl may
     182              :          * try to invoke it while still holding administrator privileges on
     183              :          * Windows.  Note that while -C can normally be in any argv position,
     184              :          * if you want to bypass the root check you must put it first.  This
     185              :          * reduces the risk that we might misinterpret some other mode's -C
     186              :          * switch as being the postmaster/postgres one.
     187              :          */
     188         1190 :         if (strcmp(argv[1], "--describe-config") == 0)
     189            0 :             do_check_root = false;
     190         1190 :         else if (argc > 2 && strcmp(argv[1], "-C") == 0)
     191            1 :             do_check_root = false;
     192              :     }
     193              : 
     194              :     /*
     195              :      * Make sure we are not running as root, unless it's safe for the selected
     196              :      * option.
     197              :      */
     198         1190 :     if (do_check_root)
     199         1189 :         check_root(progname);
     200              : 
     201              :     /*
     202              :      * Dispatch to one of various subprograms depending on first argument.
     203              :      */
     204              : 
     205         1190 :     if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-')
     206          251 :         dispatch_option = parse_dispatch_option(&argv[1][2]);
     207              : 
     208         1190 :     switch (dispatch_option)
     209              :     {
     210          126 :         case DISPATCH_CHECK:
     211          126 :             BootstrapModeMain(argc, argv, true);
     212              :             break;
     213           52 :         case DISPATCH_BOOT:
     214           52 :             BootstrapModeMain(argc, argv, false);
     215              :             break;
     216            0 :         case DISPATCH_FORKCHILD:
     217              : #ifdef EXEC_BACKEND
     218              :             SubPostmasterMain(argc, argv);
     219              : #else
     220              :             Assert(false);      /* should never happen */
     221              : #endif
     222            0 :             break;
     223            0 :         case DISPATCH_DESCRIBE_CONFIG:
     224            0 :             GucInfoMain();
     225              :             break;
     226           72 :         case DISPATCH_SINGLE:
     227           72 :             PostgresSingleUserMain(argc, argv,
     228           72 :                                    strdup(get_user_name_or_exit(progname)));
     229              :             break;
     230          940 :         case DISPATCH_POSTMASTER:
     231          940 :             PostmasterMain(argc, argv);
     232              :             break;
     233              :     }
     234              : 
     235              :     /* the functions above should not return */
     236            0 :     abort();
     237              : }
     238              : 
     239              : /*
     240              :  * Returns the matching DispatchOption value for the given option name.  If no
     241              :  * match is found, DISPATCH_POSTMASTER is returned.
     242              :  */
     243              : DispatchOption
     244         1077 : parse_dispatch_option(const char *name)
     245              : {
     246         5552 :     for (int i = 0; i < lengthof(DispatchOptionNames); i++)
     247              :     {
     248              :         /*
     249              :          * Unlike the other dispatch options, "forkchild" takes an argument,
     250              :          * so we just look for the prefix for that one.  For non-EXEC_BACKEND
     251              :          * builds, we never want to return DISPATCH_FORKCHILD, so skip over it
     252              :          * in that case.
     253              :          */
     254         4725 :         if (i == DISPATCH_FORKCHILD)
     255              :         {
     256              : #ifdef EXEC_BACKEND
     257              :             if (strncmp(DispatchOptionNames[DISPATCH_FORKCHILD], name,
     258              :                         strlen(DispatchOptionNames[DISPATCH_FORKCHILD])) == 0)
     259              :                 return DISPATCH_FORKCHILD;
     260              : #endif
     261          899 :             continue;
     262              :         }
     263              : 
     264         3826 :         if (strcmp(DispatchOptionNames[i], name) == 0)
     265          250 :             return (DispatchOption) i;
     266              :     }
     267              : 
     268              :     /* no match means this is a postmaster */
     269          827 :     return DISPATCH_POSTMASTER;
     270              : }
     271              : 
     272              : /*
     273              :  * Place platform-specific startup hacks here.  This is the right
     274              :  * place to put code that must be executed early in the launch of any new
     275              :  * server process.  Note that this code will NOT be executed when a backend
     276              :  * or sub-bootstrap process is forked, unless we are in a fork/exec
     277              :  * environment (ie EXEC_BACKEND is defined).
     278              :  *
     279              :  * XXX The need for code here is proof that the platform in question
     280              :  * is too brain-dead to provide a standard C execution environment
     281              :  * without help.  Avoid adding more here, if you can.
     282              :  */
     283              : static void
     284         2014 : startup_hacks(const char *progname)
     285              : {
     286              :     /*
     287              :      * Windows-specific execution environment hacking.
     288              :      */
     289              : #ifdef WIN32
     290              :     {
     291              :         WSADATA     wsaData;
     292              :         int         err;
     293              : 
     294              :         /* Make output streams unbuffered by default */
     295              :         setvbuf(stdout, NULL, _IONBF, 0);
     296              :         setvbuf(stderr, NULL, _IONBF, 0);
     297              : 
     298              :         /* Prepare Winsock */
     299              :         err = WSAStartup(MAKEWORD(2, 2), &wsaData);
     300              :         if (err != 0)
     301              :         {
     302              :             write_stderr("%s: WSAStartup failed: %d\n",
     303              :                          progname, err);
     304              :             exit(1);
     305              :         }
     306              : 
     307              :         /*
     308              :          * By default abort() only generates a crash-dump in *non* debug
     309              :          * builds. As our Assert() / ExceptionalCondition() uses abort(),
     310              :          * leaving the default in place would make debugging harder.
     311              :          *
     312              :          * MINGW's own C runtime doesn't have _set_abort_behavior(). When
     313              :          * targeting Microsoft's UCRT with mingw, it never links to the debug
     314              :          * version of the library and thus doesn't need the call to
     315              :          * _set_abort_behavior() either.
     316              :          */
     317              : #if !defined(__MINGW32__) && !defined(__MINGW64__)
     318              :         _set_abort_behavior(_CALL_REPORTFAULT | _WRITE_ABORT_MSG,
     319              :                             _CALL_REPORTFAULT | _WRITE_ABORT_MSG);
     320              : #endif                          /* !defined(__MINGW32__) &&
     321              :                                  * !defined(__MINGW64__) */
     322              : 
     323              :         /*
     324              :          * SEM_FAILCRITICALERRORS causes more errors to be reported to
     325              :          * callers.
     326              :          *
     327              :          * We used to also specify SEM_NOGPFAULTERRORBOX, but that prevents
     328              :          * windows crash reporting from working. Which includes registered
     329              :          * just-in-time debuggers, making it unnecessarily hard to debug
     330              :          * problems on windows. Now we try to disable sources of popups
     331              :          * separately below (note that SEM_NOGPFAULTERRORBOX did not actually
     332              :          * prevent all sources of such popups).
     333              :          */
     334              :         SetErrorMode(SEM_FAILCRITICALERRORS);
     335              : 
     336              :         /*
     337              :          * Show errors on stderr instead of popup box (note this doesn't
     338              :          * affect errors originating in the C runtime, see below).
     339              :          */
     340              :         _set_error_mode(_OUT_TO_STDERR);
     341              : 
     342              :         /*
     343              :          * In DEBUG builds, errors, including assertions, C runtime errors are
     344              :          * reported via _CrtDbgReport. By default such errors are displayed
     345              :          * with a popup (even with NOGPFAULTERRORBOX), preventing forward
     346              :          * progress. Instead report such errors stderr (and the debugger).
     347              :          * This is C runtime specific and thus the above incantations aren't
     348              :          * sufficient to suppress these popups.
     349              :          */
     350              :         _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
     351              :         _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
     352              :         _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
     353              :         _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
     354              :         _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
     355              :         _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
     356              :     }
     357              : #endif                          /* WIN32 */
     358         2014 : }
     359              : 
     360              : 
     361              : /*
     362              :  * Make the initial permanent setting for a locale category.  If that fails,
     363              :  * perhaps due to LC_foo=invalid in the environment, use locale C.  If even
     364              :  * that fails, perhaps due to out-of-memory, the entire startup fails with it.
     365              :  * When this returns, we are guaranteed to have a setting for the given
     366              :  * category's environment variable.
     367              :  */
     368              : static void
     369        12084 : init_locale(const char *categoryname, int category, const char *locale)
     370              : {
     371        12084 :     if (pg_perm_setlocale(category, locale) == NULL &&
     372            0 :         pg_perm_setlocale(category, "C") == NULL)
     373            0 :         elog(FATAL, "could not adopt \"%s\" locale nor C locale for %s",
     374              :              locale, categoryname);
     375        12084 : }
     376              : 
     377              : 
     378              : 
     379              : /*
     380              :  * Help display should match the options accepted by PostmasterMain()
     381              :  * and PostgresMain().
     382              :  *
     383              :  * XXX On Windows, non-ASCII localizations of these messages only display
     384              :  * correctly if the console output code page covers the necessary characters.
     385              :  * Messages emitted in write_console() do not exhibit this problem.
     386              :  */
     387              : static void
     388            1 : help(const char *progname)
     389              : {
     390            1 :     printf(_("%s is the PostgreSQL server.\n\n"), progname);
     391            1 :     printf(_("Usage:\n  %s [OPTION]...\n\n"), progname);
     392            1 :     printf(_("Options:\n"));
     393            1 :     printf(_("  -B NBUFFERS        number of shared buffers\n"));
     394            1 :     printf(_("  -c NAME=VALUE      set run-time parameter\n"));
     395            1 :     printf(_("  -C NAME            print value of run-time parameter, then exit\n"));
     396            1 :     printf(_("  -d 1-5             debugging level\n"));
     397            1 :     printf(_("  -D DATADIR         database directory\n"));
     398            1 :     printf(_("  -e                 use European date input format (DMY)\n"));
     399            1 :     printf(_("  -F                 turn fsync off\n"));
     400            1 :     printf(_("  -h HOSTNAME        host name or IP address to listen on\n"));
     401            1 :     printf(_("  -i                 enable TCP/IP connections (deprecated)\n"));
     402            1 :     printf(_("  -k DIRECTORY       Unix-domain socket location\n"));
     403              : #ifdef USE_SSL
     404            1 :     printf(_("  -l                 enable SSL connections\n"));
     405              : #endif
     406            1 :     printf(_("  -N MAX-CONNECT     maximum number of allowed connections\n"));
     407            1 :     printf(_("  -p PORT            port number to listen on\n"));
     408            1 :     printf(_("  -s                 show statistics after each query\n"));
     409            1 :     printf(_("  -S WORK-MEM        set amount of memory for sorts (in kB)\n"));
     410            1 :     printf(_("  -V, --version      output version information, then exit\n"));
     411            1 :     printf(_("  --NAME=VALUE       set run-time parameter\n"));
     412            1 :     printf(_("  --describe-config  describe configuration parameters, then exit\n"));
     413            1 :     printf(_("  -?, --help         show this help, then exit\n"));
     414              : 
     415            1 :     printf(_("\nDeveloper options:\n"));
     416            1 :     printf(_("  -f s|i|o|b|t|n|m|h forbid use of some plan types\n"));
     417            1 :     printf(_("  -O                 allow system table structure changes\n"));
     418            1 :     printf(_("  -P                 disable system indexes\n"));
     419            1 :     printf(_("  -t pa|pl|ex        show timings after each query\n"));
     420            1 :     printf(_("  -T                 send SIGABRT to all backend processes if one dies\n"));
     421            1 :     printf(_("  -W NUM             wait NUM seconds to allow attach from a debugger\n"));
     422              : 
     423            1 :     printf(_("\nOptions for single-user mode:\n"));
     424            1 :     printf(_("  --single           selects single-user mode (must be first argument)\n"));
     425            1 :     printf(_("  DBNAME             database name (defaults to user name)\n"));
     426            1 :     printf(_("  -d 0-5             override debugging level\n"));
     427            1 :     printf(_("  -E                 echo statement before execution\n"));
     428            1 :     printf(_("  -j                 do not use newline as interactive query delimiter\n"));
     429            1 :     printf(_("  -r FILENAME        send stdout and stderr to given file\n"));
     430              : 
     431            1 :     printf(_("\nOptions for bootstrapping mode:\n"));
     432            1 :     printf(_("  --boot             selects bootstrapping mode (must be first argument)\n"));
     433            1 :     printf(_("  --check            selects check mode (must be first argument)\n"));
     434            1 :     printf(_("  DBNAME             database name (mandatory argument in bootstrapping mode)\n"));
     435            1 :     printf(_("  -r FILENAME        send stdout and stderr to given file\n"));
     436              : 
     437            1 :     printf(_("\nPlease read the documentation for the complete list of run-time\n"
     438              :              "configuration settings and how to set them on the command line or in\n"
     439              :              "the configuration file.\n\n"
     440              :              "Report bugs to <%s>.\n"), PACKAGE_BUGREPORT);
     441            1 :     printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
     442            1 : }
     443              : 
     444              : 
     445              : 
     446              : static void
     447         1189 : check_root(const char *progname)
     448              : {
     449              : #ifndef WIN32
     450         1189 :     if (geteuid() == 0)
     451              :     {
     452            0 :         write_stderr("\"root\" execution of the PostgreSQL server is not permitted.\n"
     453              :                      "The server must be started under an unprivileged user ID to prevent\n"
     454              :                      "possible system security compromise.  See the documentation for\n"
     455              :                      "more information on how to properly start the server.\n");
     456            0 :         exit(1);
     457              :     }
     458              : 
     459              :     /*
     460              :      * Also make sure that real and effective uids are the same. Executing as
     461              :      * a setuid program from a root shell is a security hole, since on many
     462              :      * platforms a nefarious subroutine could setuid back to root if real uid
     463              :      * is root.  (Since nobody actually uses postgres as a setuid program,
     464              :      * trying to actively fix this situation seems more trouble than it's
     465              :      * worth; we'll just expend the effort to check for it.)
     466              :      */
     467         1189 :     if (getuid() != geteuid())
     468              :     {
     469            0 :         write_stderr("%s: real and effective user IDs must match\n",
     470              :                      progname);
     471            0 :         exit(1);
     472              :     }
     473              : #else                           /* WIN32 */
     474              :     if (pgwin32_is_admin())
     475              :     {
     476              :         write_stderr("Execution of PostgreSQL by a user with administrative permissions is not\n"
     477              :                      "permitted.\n"
     478              :                      "The server must be started under an unprivileged user ID to prevent\n"
     479              :                      "possible system security compromises.  See the documentation for\n"
     480              :                      "more information on how to properly start the server.\n");
     481              :         exit(1);
     482              :     }
     483              : #endif                          /* WIN32 */
     484         1189 : }
     485              : 
     486              : /*
     487              :  * At least on linux, set_ps_display() breaks /proc/$pid/environ. The
     488              :  * sanitizer library uses /proc/$pid/environ to implement getenv() as it wants
     489              :  * to work independent of libc. Depending on which sanitizers are enabled,
     490              :  * the sanitizer library may not get initialized until after we've called
     491              :  * set_ps_display(), preventing the sanitizer from seeing environment-supplied
     492              :  * options.
     493              :  *
     494              :  * We can work around that by defining __ubsan_default_options, a weak symbol
     495              :  * libsanitizer uses to get defaults from the application, and return
     496              :  * getenv("UBSAN_OPTIONS"). But only if main already was reached, so that we
     497              :  * don't end up relying on a not-yet-working getenv().
     498              :  *
     499              :  * On the other hand, with different sanitizers enabled, libsanitizer can
     500              :  * call this so early that it's not fully initialized itself, resulting in
     501              :  * recursion and a core dump within libsanitizer.  To prevent that, ensure
     502              :  * that this function is built without any sanitizer callbacks in it.
     503              :  *
     504              :  * As this function won't get called when not running a sanitizer, it doesn't
     505              :  * seem necessary to only compile it conditionally.
     506              :  */
     507              : const char *__ubsan_default_options(void);
     508              : 
     509              : #if __has_attribute(disable_sanitizer_instrumentation)
     510              : __attribute__((disable_sanitizer_instrumentation))
     511              : #endif
     512              : const char *
     513            0 : __ubsan_default_options(void)
     514              : {
     515              :     /* don't call libc before it's guaranteed to be initialized */
     516            0 :     if (!reached_main)
     517            0 :         return "";
     518              : 
     519            0 :     return getenv("UBSAN_OPTIONS");
     520              : }
        

Generated by: LCOV version 2.0-1