📄 postmaster.c
字号:
* program was run as 'postgres -M' instead of * 'postmaster' */ break; case 'N': /* The max number of backends to start. */ SetConfigOption("max_connections", optarg, PGC_POSTMASTER, PGC_S_ARGV); break; case 'n': /* Don't reinit shared mem after abnormal exit */ Reinit = false; break; case 'o': /* * Other options to pass to the backend on the command * line -- useful only for debugging. */ strcat(ExtraOptions, " "); strcat(ExtraOptions, optarg); strcpy(original_extraoptions, optarg); break; case 'p': SetConfigOption("port", optarg, PGC_POSTMASTER, PGC_S_ARGV); break; case 'S': /* * Start in 'S'ilent mode (disassociate from controlling * tty). You may also think of this as 'S'ysV mode since * it's most badly needed on SysV-derived systems like * SVR4 and HP-UX. */ SetConfigOption("silent_mode", "true", PGC_POSTMASTER, PGC_S_ARGV); break; case 's': /* * In the event that some backend dumps core, send * SIGSTOP, rather than SIGQUIT, to all its peers. This * lets the wily post_hacker collect core dumps from * everyone. */ SendStop = true; break; case 'c': case '-': { char *name, *value; ParseLongOption(optarg, &name, &value); if (!value) { if (opt == '-') ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("--%s requires a value", optarg))); else ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("-c %s requires a value", optarg))); } SetConfigOption(name, value, PGC_POSTMASTER, PGC_S_ARGV); free(name); if (value) free(value); break; } default: fprintf(stderr, gettext("Try \"%s --help\" for more information.\n"), progname); ExitPostmaster(1); } } /* * Postmaster accepts no non-option switch arguments. */ if (optind < argc) { postmaster_error("invalid argument: \"%s\"", argv[optind]); fprintf(stderr, gettext("Try \"%s --help\" for more information.\n"), progname); ExitPostmaster(1); } /* * Now we can set the data directory, and then read postgresql.conf. */ checkDataDir(potential_DataDir); /* issues error messages */ SetDataDir(potential_DataDir); ProcessConfigFile(PGC_POSTMASTER);#ifdef EXEC_BACKEND write_nondefault_variables(PGC_POSTMASTER);#endif /* * Check for invalid combinations of GUC settings. */ if (NBuffers < 2 * MaxBackends || NBuffers < 16) { /* * Do not accept -B so small that backends are likely to starve * for lack of buffers. The specific choices here are somewhat * arbitrary. */ postmaster_error("the number of buffers (-B) must be at least twice the number of allowed connections (-N) and at least 16"); ExitPostmaster(1); } if (ReservedBackends >= MaxBackends) { postmaster_error("superuser_reserved_connections must be less than max_connections"); ExitPostmaster(1); } /* * Other one-time internal sanity checks can go here. */ if (!CheckDateTokenTables()) { postmaster_error("invalid datetoken tables, please fix"); ExitPostmaster(1); } /* * Now that we are done processing the postmaster arguments, reset * getopt(3) library so that it will work correctly in subprocesses. */ optind = 1;#ifdef HAVE_INT_OPTRESET optreset = 1; /* some systems need this too */#endif /* For debugging: display postmaster environment */ { extern char **environ; char **p; ereport(DEBUG3, (errmsg_internal("%s: PostmasterMain: initial environ dump:", progname))); ereport(DEBUG3, (errmsg_internal("-----------------------------------------"))); for (p = environ; *p; ++p) ereport(DEBUG3, (errmsg_internal("\t%s", *p))); ereport(DEBUG3, (errmsg_internal("-----------------------------------------"))); } /* * On some systems our dynloader code needs the executable's pathname. */ if (FindExec(pg_pathname, progname, "postgres") < 0) ereport(FATAL, (errmsg("%s: could not locate postgres executable", progname))); /* * Initialize SSL library, if specified. */#ifdef USE_SSL if (EnableSSL && !NetServer) { postmaster_error("TCP/IP connections must be enabled for SSL"); ExitPostmaster(1); } if (EnableSSL) secure_initialize();#endif /* * process any libraries that should be preloaded and optionally * pre-initialized */ if (preload_libraries_string) process_preload_libraries(preload_libraries_string); /* * Fork away from controlling terminal, if -S specified. * * Must do this before we grab any interlock files, else the interlocks * will show the wrong PID. */ if (SilentMode) pmdaemonize(argc, argv); /* * Create lockfile for data directory. * * We want to do this before we try to grab the input sockets, because * the data directory interlock is more reliable than the socket-file * interlock (thanks to whoever decided to put socket files in /tmp * :-(). For the same reason, it's best to grab the TCP socket before * the Unix socket. */ CreateDataDirLockFile(DataDir, true); /* * Remove old temporary files. At this point there can be no other * Postgres processes running in this directory, so this should be * safe. */ RemovePgTempFiles(); /* * Establish input sockets. */ for (i = 0; i < MAXLISTEN; i++) ListenSocket[i] = -1; if (NetServer) { if (VirtualHost && VirtualHost[0]) { char *curhost, *endptr; char c = 0; curhost = VirtualHost; for (;;) { while (*curhost == ' ') /* skip any extra spaces */ curhost++; if (*curhost == '\0') break; endptr = strchr(curhost, ' '); if (endptr) { c = *endptr; *endptr = '\0'; } status = StreamServerPort(AF_UNSPEC, curhost, (unsigned short) PostPortNumber, UnixSocketDir, ListenSocket, MAXLISTEN); if (status != STATUS_OK) ereport(FATAL, (errmsg("could not create listen socket for \"%s\"", curhost))); if (endptr) { *endptr = c; curhost = endptr + 1; } else break; } } else { status = StreamServerPort(AF_UNSPEC, NULL, (unsigned short) PostPortNumber, UnixSocketDir, ListenSocket, MAXLISTEN); if (status != STATUS_OK) ereport(FATAL, (errmsg("could not create TCP/IP listen socket"))); }#ifdef USE_RENDEZVOUS if (rendezvous_name != NULL) { DNSServiceRegistrationCreate(rendezvous_name, "_postgresql._tcp.", "", htonl(PostPortNumber), "", (DNSServiceRegistrationReply) reg_reply, NULL); }#endif }#ifdef HAVE_UNIX_SOCKETS status = StreamServerPort(AF_UNIX, NULL, (unsigned short) PostPortNumber, UnixSocketDir, ListenSocket, MAXLISTEN); if (status != STATUS_OK) ereport(FATAL, (errmsg("could not create Unix-domain socket")));#endif XLOGPathInit(); /* * Set up shared memory and semaphores. */ reset_shared(PostPortNumber); /* * Estimate number of openable files. This must happen after setting up * semaphores, because on some platforms semaphores count as open files. */ set_max_safe_fds(); /* * Initialize the list of active backends. */ BackendList = DLNewList(); /* * Record postmaster options. We delay this till now to avoid * recording bogus options (eg, NBuffers too high for available * memory). */ if (!CreateOptsFile(argc, argv)) ExitPostmaster(1); /* * Set up signal handlers for the postmaster process. * * CAUTION: when changing this list, check for side-effects on the signal * handling setup of child processes. See tcop/postgres.c, * bootstrap/bootstrap.c, and postmaster/pgstat.c. */ pqinitmask(); PG_SETMASK(&BlockSig); pqsignal(SIGHUP, SIGHUP_handler); /* reread config file and have * children do same */ pqsignal(SIGINT, pmdie); /* send SIGTERM and ShutdownDataBase */ pqsignal(SIGQUIT, pmdie); /* send SIGQUIT and die */ pqsignal(SIGTERM, pmdie); /* wait for children and ShutdownDataBase */ pqsignal(SIGALRM, SIG_IGN); /* ignored */ pqsignal(SIGPIPE, SIG_IGN); /* ignored */ pqsignal(SIGUSR1, sigusr1_handler); /* message from child process */ pqsignal(SIGUSR2, dummy_handler); /* unused, reserve for children */ pqsignal(SIGCHLD, reaper); /* handle child termination */ pqsignal(SIGTTIN, SIG_IGN); /* ignored */ pqsignal(SIGTTOU, SIG_IGN); /* ignored */ /* ignore SIGXFSZ, so that ulimit violations work like disk full */#ifdef SIGXFSZ pqsignal(SIGXFSZ, SIG_IGN); /* ignored */#endif /* * Reset whereToSendOutput from Debug (its starting state) to None. * This prevents ereport from sending log messages to stderr unless * the syslog/stderr switch permits. We don't do this until the * postmaster is fully launched, since startup failures may as well be * reported to stderr. */ whereToSendOutput = None; /* * On many platforms, the first call of localtime() incurs significant * overhead to load timezone info from the system configuration files. * By doing it once in the postmaster, we avoid having to do it in * every started child process. The savings are not huge, but they * add up... */ { time_t now = time(NULL); (void) localtime(&now); } /* * Initialize and try to startup the statistics collector process */ pgstat_init(); pgstat_start(); /* * Load cached files for client authentication. */ load_hba(); load_ident(); load_user(); load_group(); /* * We're ready to rock and roll... */ StartupPID = StartupDataBase(); status = ServerLoop(); /* * ServerLoop probably shouldn't ever return, but if it does, close * down. */ ExitPostmaster(status != STATUS_OK); return 0; /* not reached */}static voidpmdaemonize(int argc, char *argv[]){ int i; pid_t pid;#ifdef LINUX_PROFILE struct itimerval prof_itimer;#endif#ifdef LINUX_PROFILE /* see comments in BackendStartup */ getitimer(ITIMER_PROF, &prof_itimer);#endif pid = fork(); if (pid == (pid_t) -1) { postmaster_error("could not fork background process: %s", strerror(errno)); ExitPostmaster(1); } else if (pid) { /* parent */ /* Parent should just exit, without doing any atexit cleanup */ _exit(0); }#ifdef LINUX_PROFILE setitimer(ITIMER_PROF, &prof_itimer, NULL);#endif MyProcPid = getpid(); /* reset MyProcPid to child *//* GH: If there's no setsid(), we hopefully don't need silent mode. * Until there's a better solution. */#ifdef HAVE_SETSID if (setsid() < 0) { postmaster_error("could not dissociate from controlling TTY: %s", strerror(errno)); ExitPostmaster(1); }#endif i = open(NULL_DEV, O_RDWR | PG_BINARY); dup2(i, 0); dup2(i, 1); dup2(i, 2); close(i);}/* * Print out help message */static voidusage(const char *progname){ printf(gettext("%s is the PostgreSQL server.\n\n"), progname); printf(gettext("Usage:\n %s [OPTION]...\n\n"), progname); printf(gettext("Options:\n"));#ifdef USE_ASSERT_CHECKING printf(gettext(" -A 1|0 enable/disable run-time assert checking\n"));#endif printf(gettext(" -B NBUFFERS number of shared buffers\n")); printf(gettext(" -c NAME=VALUE set run-time parameter\n")); printf(gettext(" -d 1-5 debugging level\n")); printf(gettext(" -D DATADIR database directory\n")); printf(gettext(" -F turn fsync off\n")); printf(gettext(" -h HOSTNAME host name or IP address to listen on\n")); printf(gettext(" -i enable TCP/IP connections\n")); printf(gettext(" -k DIRECTORY Unix-domain socket location\n"));#ifdef USE_SSL printf(gettext(" -l enable SSL connections\n"));#endif printf(gettext(" -N MAX-CONNECT maximum number of allowed connections\n")); printf(gettext(" -o OPTIONS pass \"OPTIONS\" to each server process\n")); printf(gettext(" -p PORT port number to listen on\n")); printf(gettext(" -S silent mode (start in background without logging output)\n")); printf(gettext(" --help show this help, then exit\n")); printf(gettext(" --version output version information, then exit\n")); printf(gettext("\nDeveloper options:\n")); printf(gettext(" -n do not reinitialize shared memory after abnormal exit\n")); printf(gettext(" -s send SIGSTOP to all backend servers if one dies\n")); printf(gettext("\nPlease read the documentation for the complete list of run-time\n" "configuration settings and how to set them on the command line or in\n" "the configuration file.\n\n" "Report bugs to <pgsql-bugs@postgresql.org>.\n"));}static intServerLoop(void){ fd_set readmask; int nSockets; struct timeval now, later; struct timezone tz; int i; gettimeofday(&now, &tz); nSockets = initMasks(&readmask); for (;;) { Port *port;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -