📄 postmaster.c
字号:
/* Multiplexed backends no longer supported. */ break; case 'M': /* * ignore this flag. This may be passed in because the * 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 */ snprintf(ExtraOptions + strlen(ExtraOptions), sizeof(ExtraOptions) - strlen(ExtraOptions), " %s", 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: write_stderr("Try \"%s --help\" for more information.\n", progname); ExitPostmaster(1); } } /* * Postmaster accepts no non-option switch arguments. */ if (optind < argc) { write_stderr("%s: invalid argument: \"%s\"\n", progname, argv[optind]); write_stderr("Try \"%s --help\" for more information.\n", progname); ExitPostmaster(1); }#ifdef EXEC_BACKEND /* Locate executable backend before we change working directory */ if (find_other_exec(argv[0], "postgres", PG_VERSIONSTR, postgres_exec_path) < 0) ereport(FATAL, (errmsg("%s: could not locate matching postgres executable", progname)));#endif /* * Locate the proper configuration files and data directory, and read * postgresql.conf for the first time. */ if (!SelectConfigFiles(userDoption, progname)) ExitPostmaster(2); /* Verify that DataDir looks reasonable */ checkDataDir(); /* And switch working directory into it */ ChangeToDataDir(); /* * 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. */ write_stderr("%s: the number of buffers (-B) must be at least twice the number of allowed connections (-N) and at least 16\n", progname); ExitPostmaster(1); } if (ReservedBackends >= MaxBackends) { write_stderr("%s: superuser_reserved_connections must be less than max_connections\n", progname); ExitPostmaster(1); } /* * Other one-time internal sanity checks can go here, if they are fast. * (Put any slow processing further down, after postmaster.pid creation.) */ if (!CheckDateTokenTables()) { write_stderr("%s: invalid datetoken tables, please fix\n", progname); 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("-----------------------------------------"))); } /* * 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(); /* * 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(s) before the * Unix socket. */ CreateDataDirLockFile(true); /* * If timezone is not set, determine what the OS uses. (In theory this * should be done during GUC initialization, but because it can take as * much as several seconds, we delay it until after we've created the * postmaster.pid file. This prevents problems with boot scripts that * expect the pidfile to appear quickly.) */ pg_timezone_initialize(); /* * Initialize SSL library, if specified. */#ifdef USE_SSL 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); /* * 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 (ListenAddresses) { char *rawstring; List *elemlist; ListCell *l; int success = 0; /* Need a modifiable copy of ListenAddresses */ rawstring = pstrdup(ListenAddresses); /* Parse string into list of identifiers */ if (!SplitIdentifierString(rawstring, ',', &elemlist)) { /* syntax error in list */ ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("invalid list syntax for \"listen_addresses\""))); } foreach(l, elemlist) { char *curhost = (char *) lfirst(l); if (strcmp(curhost, "*") == 0) status = StreamServerPort(AF_UNSPEC, NULL, (unsigned short) PostPortNumber, UnixSocketDir, ListenSocket, MAXLISTEN); else status = StreamServerPort(AF_UNSPEC, curhost, (unsigned short) PostPortNumber, UnixSocketDir, ListenSocket, MAXLISTEN); if (status == STATUS_OK) success++; else ereport(WARNING, (errmsg("could not create listen socket for \"%s\"", curhost))); } if (!success && list_length(elemlist)) ereport(FATAL, (errmsg("could not create any TCP/IP sockets"))); list_free(elemlist); pfree(rawstring); }#ifdef USE_BONJOUR /* Register for Bonjour only if we opened TCP socket(s) */ if (ListenSocket[0] != -1 && bonjour_name != NULL) { DNSServiceRegistrationCreate(bonjour_name, "_postgresql._tcp.", "", htons(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(WARNING, (errmsg("could not create Unix-domain socket")));#endif /* * check that we have some socket to listen on */ if (ListenSocket[0] == -1) ereport(FATAL, (errmsg("no socket created for listening"))); /* * 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();#ifdef WIN32 /* * Initialize the child pid/HANDLE arrays for signal handling. */ win32_childPIDArray = (pid_t *) malloc(mul_size(NUM_BACKENDARRAY_ELEMS, sizeof(pid_t))); win32_childHNDArray = (HANDLE *) malloc(mul_size(NUM_BACKENDARRAY_ELEMS, sizeof(HANDLE))); if (!win32_childPIDArray || !win32_childHNDArray) ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("out of memory"))); /* * Set up a handle that child processes can use to check whether the * postmaster is still running. */ if (DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &PostmasterHandle, 0, TRUE, DUPLICATE_SAME_ACCESS) == 0) ereport(FATAL, (errmsg_internal("could not duplicate postmaster handle: error code %d", (int) GetLastError())));#endif /* * Record postmaster options. We delay this till now to avoid recording * bogus options (eg, NBuffers too high for available memory). */ if (!CreateOptsFile(argc, argv, my_exec_path)) ExitPostmaster(1);#ifdef EXEC_BACKEND write_nondefault_variables(PGC_POSTMASTER);#endif /* * Write the external PID file if requested */ if (external_pid_file) { FILE *fpidfile = fopen(external_pid_file, "w"); if (fpidfile) { fprintf(fpidfile, "%d\n", MyProcPid); fclose(fpidfile); /* Should we remove the pid file on postmaster exit? */ } else write_stderr("%s: could not write external PID file \"%s\": %s\n", progname, external_pid_file, strerror(errno)); } /* * 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, postmaster/bgwriter.c, postmaster/autovacuum.c, * postmaster/pgarch.c, postmaster/pgstat.c, and postmaster/syslogger.c. */ pqinitmask(); PG_SETMASK(&BlockSig); pqsignal(SIGHUP, SIGHUP_handler); /* reread config file and have * children do same */ pqsignal(SIGINT, pmdie); /* send SIGTERM and shut down */ pqsignal(SIGQUIT, pmdie); /* send SIGQUIT and die */ pqsignal(SIGTERM, pmdie); /* wait for children and shut down */ 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 /* * If enabled, start up syslogger collection subprocess */ SysLoggerPID = SysLogger_Start(); /* * Reset whereToSendOutput from DestDebug (its starting state) to * DestNone. This stops ereport from sending log messages to stderr unless * Log_destination permits. We don't do this until the postmaster is * fully launched, since startup failures may as well be reported to * stderr. */ whereToSendOutput = DestNone; /* * Initialize the statistics collector stuff */ pgstat_init(); /* * Load configuration files for client authentication. */ load_hba(); load_ident(); /* * We're ready to rock and roll... */ StartupPID = StartupDataBase(); /* * Remember postmaster startup time */ PgStartTime = GetCurrentTimestamp(); /* * Initialize the autovacuum daemon */ autovac_init(); status = ServerLoop(); /* * ServerLoop probably shouldn't ever return, but if it does, close down. */ ExitPostmaster(status != STATUS_OK); return 0; /* not reached */}/* * Validate the proposed data directory */static voidcheckDataDir(void){ char path[MAXPGPATH]; FILE *fp; struct stat stat_buf; Assert(DataDir); if (stat(DataDir, &stat_buf) != 0) { if (errno == ENOENT) ereport(FATAL, (errcode_for_file_access(), errmsg("data directory \"%s\" does not exist", DataDir))); else ereport(FATAL, (errcode_for_file_access(), errmsg("could not read permissions of directory \"%s\": %m", DataDir))); } /* * Check that the directory belongs to my userid; if not, reject. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -