From 3892a2d8619ee5623fc3ebee775538fdea1f529e Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 14 Nov 2010 15:57:37 -0500 Subject: [PATCH] Fix canAcceptConnections() bugs introduced by replication-related patches. We must not return any "okay to proceed" result code without having checked for too many children, else we might fail later on when trying to add the new child to one of the per-child state arrays. It's not clear whether this oversight explains Stefan Kaltenbrunner's recent report, but it could certainly produce a similar symptom. Back-patch to 8.4; the logic was not broken before that. --- src/backend/postmaster/postmaster.c | 33 +++++++++++++++++------------ 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 0fb11833fa..25500d4c9b 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -350,7 +350,7 @@ static int ProcessStartupPacket(Port *port, bool SSLdone); static void processCancelRequest(Port *port, void *pkt); static int initMasks(fd_set *rmask); static void report_fork_failure_to_client(Port *port, int errnum); -static enum CAC_state canAcceptConnections(void); +static CAC_state canAcceptConnections(void); static long PostmasterRandom(void); static void RandomSalt(char *md5Salt); static void signal_child(pid_t pid, int signal); @@ -1908,9 +1908,11 @@ processCancelRequest(Port *port, void *pkt) /* * canAcceptConnections --- check to see if database state allows connections. */ -static enum CAC_state +static CAC_state canAcceptConnections(void) { + CAC_state result = CAC_OK; + /* * Can't start backends when in startup/shutdown/inconsistent recovery * state. @@ -1918,21 +1920,24 @@ canAcceptConnections(void) * In state PM_WAIT_BACKUP only superusers can connect (this must be * allowed so that a superuser can end online backup mode); we return * CAC_WAITBACKUP code to indicate that this must be checked later. + * Note that neither CAC_OK nor CAC_WAITBACKUP can safely be returned + * until we have checked for too many children. */ if (pmState != PM_RUN) { if (pmState == PM_WAIT_BACKUP) - return CAC_WAITBACKUP; /* allow superusers only */ - if (Shutdown > NoShutdown) + result = CAC_WAITBACKUP; /* allow superusers only */ + else if (Shutdown > NoShutdown) return CAC_SHUTDOWN; /* shutdown is pending */ - if (!FatalError && - (pmState == PM_STARTUP || - pmState == PM_RECOVERY)) - return CAC_STARTUP; /* normal startup */ - if (!FatalError && - pmState == PM_HOT_STANDBY) - return CAC_OK; /* connection OK during hot standby */ - return CAC_RECOVERY; /* else must be crash recovery */ + else if (!FatalError && + (pmState == PM_STARTUP || + pmState == PM_RECOVERY)) + return CAC_STARTUP; /* normal startup */ + else if (!FatalError && + pmState == PM_HOT_STANDBY) + result = CAC_OK; /* connection OK during hot standby */ + else + return CAC_RECOVERY; /* else must be crash recovery */ } /* @@ -1948,9 +1953,9 @@ canAcceptConnections(void) * see comments for MaxLivePostmasterChildren(). */ if (CountChildren(BACKEND_TYPE_ALL) >= MaxLivePostmasterChildren()) - return CAC_TOOMANY; + result = CAC_TOOMANY; - return CAC_OK; + return result; }