Jan pointed out that elog(FATAL) out of ReverifyMyDatabase() leaves
shared memory in an un-cleaned-up state (buffer refcounts > 0).
There might also be other unaccounted-for problems, I suspect.
I do not like his fix (heap_endscan before the elog(FATAL)) because
it only plugs this specific hole in the dike, not the whole class of
problems.
The reason that the normal process-exit cleanup doesn't fix this is that
ReverifyMyDatabase() runs before we've entered the main loop in
PostgresMain, and so elog() just goes straight to proc_exit() instead of
longjmp'ing to the error recovery code in PostgresMain.
My feeling is that proc_exit() ought to be prepared to do *everything*
that is needed to shut down a backend, and that in fact elog()'s
behavior for FATAL is bogus even in the post-startup case. It should
be sufficient to call proc_exit() to exit after a FATAL error. If it
isn't, then the other half-dozen places that call proc_exit() are broken
too.
Similarly, it's broken that PostgresMain needs to do several things
before calling proc_exit. Those things ought to be done *by* proc_exit.
Accordingly, I propose registering more cleanup routines with
on_proc_exit so that the right things happen in all exit cases, whether
normal, FATAL, or backend-startup; and removing the extra calls in
elog() and PostgresMain().
Comments, objections?
regards, tom lane