Skip to content

Commit a510bf4

Browse files
committed
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.
1 parent 96ad60e commit a510bf4

File tree

1 file changed

+42
-4
lines changed

1 file changed

+42
-4
lines changed

src/backend/postmaster/postmaster.c

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
*
3838
*
3939
* IDENTIFICATION
40-
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.262 2001/12/04 16:17:48 tgl Exp $
40+
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.263 2002/01/06 21:40:02 tgl Exp $
4141
*
4242
* NOTES
4343
*
@@ -249,6 +249,7 @@ static int BackendStartup(Port *port);
249249
static int ProcessStartupPacket(Port *port, bool SSLdone);
250250
static void processCancelRequest(Port *port, void *pkt);
251251
static int initMasks(fd_set *rmask, fd_set *wmask);
252+
static void report_fork_failure_to_client(Port *port, int errnum);
252253
enum CAC_state
253254
{
254255
CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY
@@ -1864,11 +1865,11 @@ BackendStartup(Port *port)
18641865
{
18651866
int status;
18661867

1867-
free(bn);
18681868
#ifdef __BEOS__
18691869
/* Specific beos backend startup actions */
18701870
beos_backend_startup();
18711871
#endif
1872+
free(bn);
18721873

18731874
status = DoBackend(port);
18741875
if (status != 0)
@@ -1883,13 +1884,16 @@ BackendStartup(Port *port)
18831884
/* in parent, error */
18841885
if (pid < 0)
18851886
{
1886-
free(bn);
1887+
int save_errno = errno;
1888+
18871889
#ifdef __BEOS__
18881890
/* Specific beos backend startup actions */
18891891
beos_backend_startup_failed();
18901892
#endif
1893+
free(bn);
18911894
elog(DEBUG, "connection startup failed (fork failure): %s",
1892-
strerror(errno));
1895+
strerror(save_errno));
1896+
report_fork_failure_to_client(port, save_errno);
18931897
return STATUS_ERROR;
18941898
}
18951899

@@ -1910,6 +1914,40 @@ BackendStartup(Port *port)
19101914
}
19111915

19121916

1917+
/*
1918+
* Try to report backend fork() failure to client before we close the
1919+
* connection. Since we do not care to risk blocking the postmaster on
1920+
* this connection, we set the connection to non-blocking and try only once.
1921+
*
1922+
* This is grungy special-purpose code; we cannot use backend libpq since
1923+
* it's not up and running.
1924+
*/
1925+
static void
1926+
report_fork_failure_to_client(Port *port, int errnum)
1927+
{
1928+
char buffer[1000];
1929+
#ifdef __BEOS__
1930+
int on = 1;
1931+
#endif
1932+
1933+
/* Format the error message packet */
1934+
snprintf(buffer, sizeof(buffer), "E%s%s\n",
1935+
gettext("Server process fork() failed: "),
1936+
strerror(errnum));
1937+
1938+
/* Set port to non-blocking. Don't do send() if this fails */
1939+
#ifdef __BEOS__
1940+
if (ioctl(port->sock, FIONBIO, &on) != 0)
1941+
return;
1942+
#else
1943+
if (fcntl(port->sock, F_SETFL, O_NONBLOCK) < 0)
1944+
return;
1945+
#endif
1946+
1947+
send(port->sock, buffer, strlen(buffer)+1, 0);
1948+
}
1949+
1950+
19131951
/*
19141952
* split_opts -- split a string of options and append it to an argv array
19151953
*

0 commit comments

Comments
 (0)