diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c index 26d8faaf773a818b388b899b8d83d617bdf7af9b..2ddcf428f89fd12c230d6f417c2f707fbd97bf39 100644 --- a/src/backend/libpq/be-secure.c +++ b/src/backend/libpq/be-secure.c @@ -35,6 +35,7 @@ #include "miscadmin.h" #include "tcop/tcopprot.h" #include "utils/memutils.h" +#include "storage/ipc.h" #include "storage/proc.h" @@ -144,9 +145,31 @@ retry: Assert(waitfor); w = WaitLatchOrSocket(MyLatch, - WL_LATCH_SET | waitfor, + WL_LATCH_SET | WL_POSTMASTER_DEATH | waitfor, port->sock, 0); + /* + * If the postmaster has died, it's not safe to continue running, + * because it is the postmaster's job to kill us if some other backend + * exists uncleanly. Moreover, we won't run very well in this state; + * helper processes like walwriter and the bgwriter will exit, so + * performance may be poor. Finally, if we don't exit, pg_ctl will + * be unable to restart the postmaster without manual intervention, + * so no new connections can be accepted. Exiting clears the deck + * for a postmaster restart. + * + * (Note that we only make this check when we would otherwise sleep + * on our latch. We might still continue running for a while if the + * postmaster is killed in mid-query, or even through multiple queries + * if we never have to wait for read. We don't want to burn too many + * cycles checking for this very rare condition, and this should cause + * us to exit quickly in most cases.) + */ + if (w & WL_POSTMASTER_DEATH) + ereport(FATAL, + (errcode(ERRCODE_ADMIN_SHUTDOWN), + errmsg("terminating connection due to unexpected postmaster exit"))); + /* Handle interrupt. */ if (w & WL_LATCH_SET) { @@ -223,9 +246,15 @@ retry: Assert(waitfor); w = WaitLatchOrSocket(MyLatch, - WL_LATCH_SET | waitfor, + WL_LATCH_SET | WL_POSTMASTER_DEATH | waitfor, port->sock, 0); + /* See comments in secure_read. */ + if (w & WL_POSTMASTER_DEATH) + ereport(FATAL, + (errcode(ERRCODE_ADMIN_SHUTDOWN), + errmsg("terminating connection due to unexpected postmaster exit"))); + /* Handle interrupt. */ if (w & WL_LATCH_SET) {