diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-08-27 14:16:19 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-08-27 14:16:19 -0400 |
commit | ef3455f190d3c12de71c06316109bb5ffbffe462 (patch) | |
tree | c9d953d095fb4fdb2c2b826eb23ba845e401a6b5 | |
parent | 814a7f50c6c53883b0b753458c9912b0e6bc2519 (diff) | |
download | postgresql-ef3455f190d3c12de71c06316109bb5ffbffe462.tar.gz postgresql-ef3455f190d3c12de71c06316109bb5ffbffe462.zip |
Ensure we discard unread/unsent data when abandoning a connection attempt.
There are assorted situations wherein PQconnectPoll() will abandon a
connection attempt and try again with different parameters (eg, SSL versus
not SSL). However, the code forgot to discard any pending data in libpq's
I/O buffers when doing this. In at least one case (server returns E
message during SSL negotiation), there is unread input data which bollixes
the next connection attempt. I have not checked to see whether this is
possible in the other cases where we close the socket and retry, but it
seems like a matter of good defensive programming to add explicit
buffer-flushing code to all of them.
This is one of several issues exposed by Daniel Farina's report of
misbehavior after a server-side fork failure.
This has been wrong since forever, so back-patch to all supported branches.
-rw-r--r-- | src/interfaces/libpq/fe-connect.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 9e4807e8a96..72796aa4759 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -2068,6 +2068,9 @@ keep_going: /* We will come back to here until there is closesocket(conn->sock); conn->sock = -1; conn->status = CONNECTION_NEEDED; + /* Discard any unread/unsent data */ + conn->inStart = conn->inCursor = conn->inEnd = 0; + conn->outCount = 0; goto keep_going; } else @@ -2105,6 +2108,9 @@ keep_going: /* We will come back to here until there is closesocket(conn->sock); conn->sock = -1; conn->status = CONNECTION_NEEDED; + /* Discard any unread/unsent data */ + conn->inStart = conn->inCursor = conn->inEnd = 0; + conn->outCount = 0; goto keep_going; } } @@ -2218,6 +2224,9 @@ keep_going: /* We will come back to here until there is closesocket(conn->sock); conn->sock = -1; conn->status = CONNECTION_NEEDED; + /* Discard any unread/unsent data */ + conn->inStart = conn->inCursor = conn->inEnd = 0; + conn->outCount = 0; goto keep_going; } @@ -2285,6 +2294,9 @@ keep_going: /* We will come back to here until there is closesocket(conn->sock); conn->sock = -1; conn->status = CONNECTION_NEEDED; + /* Discard any unread/unsent data */ + conn->inStart = conn->inCursor = conn->inEnd = 0; + conn->outCount = 0; goto keep_going; } @@ -2304,6 +2316,9 @@ keep_going: /* We will come back to here until there is closesocket(conn->sock); conn->sock = -1; conn->status = CONNECTION_NEEDED; + /* Discard any unread/unsent data */ + conn->inStart = conn->inCursor = conn->inEnd = 0; + conn->outCount = 0; goto keep_going; } #endif @@ -2467,6 +2482,9 @@ keep_going: /* We will come back to here until there is closesocket(conn->sock); conn->sock = -1; conn->status = CONNECTION_NEEDED; + /* Discard any unread/unsent data */ + conn->inStart = conn->inCursor = conn->inEnd = 0; + conn->outCount = 0; goto keep_going; } } |