Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f0ae1e8

Browse files
committed
When closure of the backend connection is detected during pqFlush,
do the right thing: look for a NOTICE message from the backend before we close our side of the socket. 6.4 libpq did not reliably print the backend's hara-kiri message, 'The Postmaster has informed me ...', because it only did the right thing if connection closure was detected during a read attempt instead of a write attempt.
1 parent 615e77e commit f0ae1e8

File tree

2 files changed

+70
-20
lines changed

2 files changed

+70
-20
lines changed

src/interfaces/libpq/fe-exec.c

+60-11
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.80 1999/05/25 16:15:12 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.81 1999/05/28 01:54:53 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -47,6 +47,7 @@ const char *const pgresStatus[] = {
4747

4848
static int addTuple(PGresult *res, PGresAttValue *tup);
4949
static void parseInput(PGconn *conn);
50+
static void handleSendFailure(PGconn *conn);
5051
static int getRowDescriptions(PGconn *conn);
5152
static int getAnotherTuple(PGconn *conn, int binary);
5253
static int getNotify(PGconn *conn);
@@ -433,18 +434,53 @@ PQsendQuery(PGconn *conn, const char *query)
433434

434435
/* send the query to the backend; */
435436
/* the frontend-backend protocol uses 'Q' to designate queries */
436-
if (pqPutnchar("Q", 1, conn))
437-
return 0;
438-
if (pqPuts(query, conn))
439-
return 0;
440-
if (pqFlush(conn))
437+
if (pqPutnchar("Q", 1, conn) ||
438+
pqPuts(query, conn) ||
439+
pqFlush(conn))
440+
{
441+
handleSendFailure(conn);
441442
return 0;
443+
}
442444

443445
/* OK, it's launched! */
444446
conn->asyncStatus = PGASYNC_BUSY;
445447
return 1;
446448
}
447449

450+
/*
451+
* handleSendFailure: try to clean up after failure to send command.
452+
*
453+
* Primarily, what we want to accomplish here is to process an async
454+
* NOTICE message that the backend might have sent just before it died.
455+
*
456+
* NOTE: this routine should only be called in PGASYNC_IDLE state.
457+
*/
458+
459+
static void
460+
handleSendFailure(PGconn *conn)
461+
{
462+
/* Preserve the error message emitted by the failing output routine */
463+
char * svErrMsg = strdup(conn->errorMessage);
464+
465+
/*
466+
* Accept any available input data, ignoring errors. Note that if
467+
* pqReadData decides the backend has closed the channel, it will
468+
* close our side of the socket --- that's just what we want here.
469+
*/
470+
while (pqReadData(conn) > 0)
471+
/* loop until no more data readable */ ;
472+
473+
/*
474+
* Parse any available input messages. Since we are in PGASYNC_IDLE
475+
* state, only NOTICE and NOTIFY messages will be eaten.
476+
*/
477+
parseInput(conn);
478+
479+
/* Restore error message generated by output routine, if any. */
480+
if (*svErrMsg != '\0')
481+
strcpy(conn->errorMessage, svErrMsg);
482+
free(svErrMsg);
483+
}
448484

449485
/*
450486
* Consume any available input from the backend
@@ -1399,31 +1435,44 @@ PQfn(PGconn *conn,
13991435
/* clear the error string */
14001436
conn->errorMessage[0] = '\0';
14011437

1402-
if (pqPuts("F ", conn)) /* function */
1403-
return NULL;
1404-
if (pqPutInt(fnid, 4, conn))/* function id */
1405-
return NULL;
1406-
if (pqPutInt(nargs, 4, conn)) /* # of args */
1438+
if (pqPuts("F ", conn) || /* function */
1439+
pqPutInt(fnid, 4, conn) || /* function id */
1440+
pqPutInt(nargs, 4, conn)) /* # of args */
1441+
{
1442+
handleSendFailure(conn);
14071443
return NULL;
1444+
}
14081445

14091446
for (i = 0; i < nargs; ++i)
14101447
{ /* len.int4 + contents */
14111448
if (pqPutInt(args[i].len, 4, conn))
1449+
{
1450+
handleSendFailure(conn);
14121451
return NULL;
1452+
}
14131453

14141454
if (args[i].isint)
14151455
{
14161456
if (pqPutInt(args[i].u.integer, 4, conn))
1457+
{
1458+
handleSendFailure(conn);
14171459
return NULL;
1460+
}
14181461
}
14191462
else
14201463
{
14211464
if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
1465+
{
1466+
handleSendFailure(conn);
14221467
return NULL;
1468+
}
14231469
}
14241470
}
14251471
if (pqFlush(conn))
1472+
{
1473+
handleSendFailure(conn);
14261474
return NULL;
1475+
}
14271476

14281477
for (;;)
14291478
{

src/interfaces/libpq/fe-misc.c

+10-9
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
*
2525
*
2626
* IDENTIFICATION
27-
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.24 1999/05/25 16:15:13 momjian Exp $
27+
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.25 1999/05/28 01:54:53 tgl Exp $
2828
*
2929
*-------------------------------------------------------------------------
3030
*/
@@ -471,7 +471,6 @@ pqFlush(PGconn *conn)
471471
/* Prevent being SIGPIPEd if backend has closed the connection. */
472472
#ifndef WIN32
473473
pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
474-
475474
#endif
476475

477476
int sent = send(conn->sock, ptr, len, 0);
@@ -498,6 +497,7 @@ pqFlush(PGconn *conn)
498497
case EWOULDBLOCK:
499498
break;
500499
#endif
500+
501501
case EPIPE:
502502
#ifdef ECONNRESET
503503
case ECONNRESET:
@@ -506,14 +506,15 @@ pqFlush(PGconn *conn)
506506
"pqFlush() -- backend closed the channel unexpectedly.\n"
507507
"\tThis probably means the backend terminated abnormally"
508508
" before or while processing the request.\n");
509-
conn->status = CONNECTION_BAD; /* No more connection */
510-
#ifdef WIN32
511-
closesocket(conn->sock);
512-
#else
513-
close(conn->sock);
514-
#endif
515-
conn->sock = -1;
509+
/*
510+
* We used to close the socket here, but that's a bad
511+
* idea since there might be unread data waiting
512+
* (typically, a NOTICE message from the backend telling
513+
* us it's committing hara-kiri...). Leave the socket
514+
* open until pqReadData finds no more data can be read.
515+
*/
516516
return EOF;
517+
517518
default:
518519
sprintf(conn->errorMessage,
519520
"pqFlush() -- couldn't send data: errno=%d\n%s\n",

0 commit comments

Comments
 (0)