+/*
+ * Code shared between proc_exit and the atexit handler. Note that in
+ * normal exit through proc_exit, this will actually be called twice ...
+ * but the second call will have nothing to do.
+ */
+static void
+proc_exit_prepare(int code)
+{
+ /*
+ * Once we set this flag, we are committed to exit. Any ereport() will
+ * NOT send control back to the main loop, but right back here.
+ */
+ proc_exit_inprogress = true;
+
+ /*
+ * Forget any pending cancel or die requests; we're doing our best to
+ * close up shop already. Note that the signal handlers will not set
+ * these flags again, now that proc_exit_inprogress is set.
+ */
+ InterruptPending = false;
+ ProcDiePending = false;
+ QueryCancelPending = false;
+ /* And let's just make *sure* we're not interrupted ... */
+ ImmediateInterruptOK = false;
+ InterruptHoldoffCount = 1;
+ CritSectionCount = 0;
+
+ /* do our shared memory exits first */
+ shmem_exit(code);
+
+ elog(DEBUG3, "proc_exit(%d)", code);
+
+ /*
+ * call all the registered callbacks.
+ *
+ * Note that since we decrement on_proc_exit_index each time, if a
+ * callback calls ereport(ERROR) or ereport(FATAL) then it won't be
+ * invoked again when control comes back here (nor will the
+ * previously-completed callbacks). So, an infinite loop should not be
+ * possible.
+ */
+ while (--on_proc_exit_index >= 0)
+ (*on_proc_exit_list[on_proc_exit_index].function) (code,
+ on_proc_exit_list[on_proc_exit_index].arg);
+
+ on_proc_exit_index = 0;
+}
+