If we fail to fork a new backend process, (try to) report the failure

to the client before closing the connection.  Before 7.2 this was done
correctly, but new code would simply close the connection with no report
to the client.
This commit is contained in:
Tom Lane 2002-01-06 21:40:02 +00:00
parent 96ad60e919
commit a510bf4326
1 changed files with 42 additions and 4 deletions

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.262 2001/12/04 16:17:48 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.263 2002/01/06 21:40:02 tgl Exp $
*
* NOTES
*
@ -249,6 +249,7 @@ static int BackendStartup(Port *port);
static int ProcessStartupPacket(Port *port, bool SSLdone);
static void processCancelRequest(Port *port, void *pkt);
static int initMasks(fd_set *rmask, fd_set *wmask);
static void report_fork_failure_to_client(Port *port, int errnum);
enum CAC_state
{
CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY
@ -1864,11 +1865,11 @@ BackendStartup(Port *port)
{
int status;
free(bn);
#ifdef __BEOS__
/* Specific beos backend startup actions */
beos_backend_startup();
#endif
free(bn);
status = DoBackend(port);
if (status != 0)
@ -1883,13 +1884,16 @@ BackendStartup(Port *port)
/* in parent, error */
if (pid < 0)
{
free(bn);
int save_errno = errno;
#ifdef __BEOS__
/* Specific beos backend startup actions */
beos_backend_startup_failed();
#endif
free(bn);
elog(DEBUG, "connection startup failed (fork failure): %s",
strerror(errno));
strerror(save_errno));
report_fork_failure_to_client(port, save_errno);
return STATUS_ERROR;
}
@ -1910,6 +1914,40 @@ BackendStartup(Port *port)
}
/*
* Try to report backend fork() failure to client before we close the
* connection. Since we do not care to risk blocking the postmaster on
* this connection, we set the connection to non-blocking and try only once.
*
* This is grungy special-purpose code; we cannot use backend libpq since
* it's not up and running.
*/
static void
report_fork_failure_to_client(Port *port, int errnum)
{
char buffer[1000];
#ifdef __BEOS__
int on = 1;
#endif
/* Format the error message packet */
snprintf(buffer, sizeof(buffer), "E%s%s\n",
gettext("Server process fork() failed: "),
strerror(errnum));
/* Set port to non-blocking. Don't do send() if this fails */
#ifdef __BEOS__
if (ioctl(port->sock, FIONBIO, &on) != 0)
return;
#else
if (fcntl(port->sock, F_SETFL, O_NONBLOCK) < 0)
return;
#endif
send(port->sock, buffer, strlen(buffer)+1, 0);
}
/*
* split_opts -- split a string of options and append it to an argv array
*