Fix early elog(FATAL)

Noah Misch <noah@leadboat.com>

From: Noah Misch <noah@leadboat.com>
To: pgsql-hackers@postgresql.org
Cc: nathandbossart@gmail.com
Date: 2024-12-08T03:46:14Z
Lists: pgsql-hackers

Attachments

main() says:

	/*
	 * Fire up essential subsystems: error and memory management
	 *
	 * Code after this point is allowed to use elog/ereport, though
	 * localization of messages may not work right away, and messages won't go
	 * anywhere but stderr until GUC settings get loaded.
	 */
	MemoryContextInit();

However, appending elog(ERROR, "whoops") breaks like:

$ initdb -D discard_me
FATAL:  whoops
PANIC:  proc_exit() called in child process
no data was returned by command ""/home/nm/sw/nopath/pghead/bin/postgres" -V"
child process was terminated by signal 6: Aborted

So does the ereport(FATAL) in ClosePostmasterPorts().  The "called in child
process" check (added in commit 97550c0 of 2023-10) reads MyProcPid, which we
set later.  Three ways to fix this:

1. Call InitProcessGlobals() earlier.  This could also reduce the total call
   sites from 3 to 2 (main() and post-fork).

2. Move MyProcPid init out of InitProcessGlobals(), to main() and post-fork.
   This has less to go wrong in back branches.  While probably irrelevant,
   this avoids calling pg_prng_strong_seed() in processes that will exit after
   help() or GucInfoMain().

3. Revert 97550c0, as commit 3b00fdb anticipated.

I don't think the choice matters much, so here is (2).

Commits

  1. Fix elog(FATAL) before PostmasterMain() or just after fork().

  2. Remove obsolete check in SIGTERM handler for the startup process.

  3. Check that MyProcPid == getpid() in backend signal handlers.

  4. Avoid calling proc_exit() in processes forked by system().

  5. Refactor pid, random seed and start time initialization.