diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 1999-05-28 01:54:53 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 1999-05-28 01:54:53 +0000 |
commit | f0ae1e8d10d7a38029cd0009063fa5131dce7937 (patch) | |
tree | 956a7576fd28cf549772139240a5157085b35c7c /src/interfaces/libpq/fe-exec.c | |
parent | 615e77ede2f3cd25cac7725112e31fb38753e270 (diff) | |
download | postgresql-f0ae1e8d10d7a38029cd0009063fa5131dce7937.tar.gz postgresql-f0ae1e8d10d7a38029cd0009063fa5131dce7937.zip |
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.
Diffstat (limited to 'src/interfaces/libpq/fe-exec.c')
-rw-r--r-- | src/interfaces/libpq/fe-exec.c | 71 |
1 files changed, 60 insertions, 11 deletions
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index 475a51bc4ac..446a70c821a 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.80 1999/05/25 16:15:12 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.81 1999/05/28 01:54:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -47,6 +47,7 @@ const char *const pgresStatus[] = { static int addTuple(PGresult *res, PGresAttValue *tup); static void parseInput(PGconn *conn); +static void handleSendFailure(PGconn *conn); static int getRowDescriptions(PGconn *conn); static int getAnotherTuple(PGconn *conn, int binary); static int getNotify(PGconn *conn); @@ -433,18 +434,53 @@ PQsendQuery(PGconn *conn, const char *query) /* send the query to the backend; */ /* the frontend-backend protocol uses 'Q' to designate queries */ - if (pqPutnchar("Q", 1, conn)) - return 0; - if (pqPuts(query, conn)) - return 0; - if (pqFlush(conn)) + if (pqPutnchar("Q", 1, conn) || + pqPuts(query, conn) || + pqFlush(conn)) + { + handleSendFailure(conn); return 0; + } /* OK, it's launched! */ conn->asyncStatus = PGASYNC_BUSY; return 1; } +/* + * handleSendFailure: try to clean up after failure to send command. + * + * Primarily, what we want to accomplish here is to process an async + * NOTICE message that the backend might have sent just before it died. + * + * NOTE: this routine should only be called in PGASYNC_IDLE state. + */ + +static void +handleSendFailure(PGconn *conn) +{ + /* Preserve the error message emitted by the failing output routine */ + char * svErrMsg = strdup(conn->errorMessage); + + /* + * Accept any available input data, ignoring errors. Note that if + * pqReadData decides the backend has closed the channel, it will + * close our side of the socket --- that's just what we want here. + */ + while (pqReadData(conn) > 0) + /* loop until no more data readable */ ; + + /* + * Parse any available input messages. Since we are in PGASYNC_IDLE + * state, only NOTICE and NOTIFY messages will be eaten. + */ + parseInput(conn); + + /* Restore error message generated by output routine, if any. */ + if (*svErrMsg != '\0') + strcpy(conn->errorMessage, svErrMsg); + free(svErrMsg); +} /* * Consume any available input from the backend @@ -1399,31 +1435,44 @@ PQfn(PGconn *conn, /* clear the error string */ conn->errorMessage[0] = '\0'; - if (pqPuts("F ", conn)) /* function */ - return NULL; - if (pqPutInt(fnid, 4, conn))/* function id */ - return NULL; - if (pqPutInt(nargs, 4, conn)) /* # of args */ + if (pqPuts("F ", conn) || /* function */ + pqPutInt(fnid, 4, conn) || /* function id */ + pqPutInt(nargs, 4, conn)) /* # of args */ + { + handleSendFailure(conn); return NULL; + } for (i = 0; i < nargs; ++i) { /* len.int4 + contents */ if (pqPutInt(args[i].len, 4, conn)) + { + handleSendFailure(conn); return NULL; + } if (args[i].isint) { if (pqPutInt(args[i].u.integer, 4, conn)) + { + handleSendFailure(conn); return NULL; + } } else { if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn)) + { + handleSendFailure(conn); return NULL; + } } } if (pqFlush(conn)) + { + handleSendFailure(conn); return NULL; + } for (;;) { |