diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2011-08-27 14:16:25 -0400 | 
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2011-08-27 14:16:25 -0400 | 
| commit | 431b638045814137a2037add85db577a7985b19d (patch) | |
| tree | 849c7bd7778208c6adcad7c72818ab0dce60273c /src | |
| parent | 20139f4f1cdd371d230d5389acf9ec8ff150b863 (diff) | |
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.
Diffstat (limited to 'src')
| -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 0efc1700c93..d1e11a66a5f 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -1911,6 +1911,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 @@ -1948,6 +1951,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;  					}  				} @@ -2061,6 +2067,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;  					} @@ -2128,6 +2137,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;  					} @@ -2147,6 +2159,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 @@ -2308,6 +2323,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;  						}  					} | 
