From 210eb9b743c0645df05e5c8be4490ba4f09fc871 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 7 Sep 2012 16:02:23 -0400 Subject: [PATCH] Centralize libpq's low-level code for dropping a connection. Create an internal function pqDropConnection that does the physical socket close and cleans up closely-associated state. This removes a bunch of ad hoc, not always consistent closure code. The ulterior motive is to have a single place to wait for a spawned child backend to exit, but this seems like good cleanup even if that never happens. I went back and forth on whether to include "conn->status = CONNECTION_BAD" in pqDropConnection's actions, but for the moment decided not to. Only a minority of the call sites actually want that, and in any case it's arguable that conn->status is slightly higher-level state, and thus not part of this function's purview. --- src/interfaces/libpq/fe-connect.c | 95 +++++++++++------------------ src/interfaces/libpq/fe-misc.c | 5 +- src/interfaces/libpq/fe-protocol3.c | 4 +- src/interfaces/libpq/libpq-int.h | 1 + 4 files changed, 38 insertions(+), 67 deletions(-) diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 3dcd0c3f9c..9eaf41025b 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -344,6 +344,28 @@ static void default_threadlock(int acquire); pgthreadlock_t pg_g_threadlock = default_threadlock; +/* + * pqDropConnection + * + * Close any physical connection to the server, and reset associated + * state inside the connection object. We don't release state that + * would be needed to reconnect, though. + */ +void +pqDropConnection(PGconn *conn) +{ + /* Drop any SSL state */ + pqsecure_close(conn); + /* Close the socket itself */ + if (conn->sock >= 0) + closesocket(conn->sock); + conn->sock = -1; + /* Discard any unread/unsent data */ + conn->inStart = conn->inCursor = conn->inEnd = 0; + conn->outCount = 0; +} + + /* * Connecting to a Database * @@ -1416,12 +1438,7 @@ connectDBStart(PGconn *conn) return 1; connect_errReturn: - if (conn->sock >= 0) - { - pqsecure_close(conn); - closesocket(conn->sock); - conn->sock = -1; - } + pqDropConnection(conn); conn->status = CONNECTION_BAD; return 0; } @@ -1644,8 +1661,7 @@ keep_going: /* We will come back to here until there is { if (!connectNoDelay(conn)) { - closesocket(conn->sock); - conn->sock = -1; + pqDropConnection(conn); conn->addr_cur = addr_cur->ai_next; continue; } @@ -1655,8 +1671,7 @@ keep_going: /* We will come back to here until there is appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not set socket to non-blocking mode: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); - closesocket(conn->sock); - conn->sock = -1; + pqDropConnection(conn); conn->addr_cur = addr_cur->ai_next; continue; } @@ -1667,8 +1682,7 @@ keep_going: /* We will come back to here until there is appendPQExpBuffer(&conn->errorMessage, libpq_gettext("could not set socket to close-on-exec mode: %s\n"), SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf))); - closesocket(conn->sock); - conn->sock = -1; + pqDropConnection(conn); conn->addr_cur = addr_cur->ai_next; continue; } @@ -1715,8 +1729,7 @@ keep_going: /* We will come back to here until there is if (err) { - closesocket(conn->sock); - conn->sock = -1; + pqDropConnection(conn); conn->addr_cur = addr_cur->ai_next; continue; } @@ -1802,11 +1815,7 @@ keep_going: /* We will come back to here until there is * failure and keep going if there are more addresses. */ connectFailureMessage(conn, SOCK_ERRNO); - if (conn->sock >= 0) - { - closesocket(conn->sock); - conn->sock = -1; - } + pqDropConnection(conn); /* * Try the next address, if any. @@ -1851,6 +1860,7 @@ keep_going: /* We will come back to here until there is * error message. */ connectFailureMessage(conn, optval); + pqDropConnection(conn); /* * If more addresses remain, keep trying, just as in the @@ -1858,11 +1868,6 @@ keep_going: /* We will come back to here until there is */ if (conn->addr_cur->ai_next != NULL) { - if (conn->sock >= 0) - { - closesocket(conn->sock); - conn->sock = -1; - } conn->addr_cur = conn->addr_cur->ai_next; conn->status = CONNECTION_NEEDED; goto keep_going; @@ -2137,12 +2142,8 @@ keep_going: /* We will come back to here until there is /* only retry once */ conn->allow_ssl_try = false; /* Must drop the old connection */ - closesocket(conn->sock); - conn->sock = -1; + pqDropConnection(conn); conn->status = CONNECTION_NEEDED; - /* Discard any unread/unsent data */ - conn->inStart = conn->inCursor = conn->inEnd = 0; - conn->outCount = 0; goto keep_going; } } @@ -2252,13 +2253,8 @@ keep_going: /* We will come back to here until there is { conn->pversion = PG_PROTOCOL(2, 0); /* Must drop the old connection */ - pqsecure_close(conn); - closesocket(conn->sock); - conn->sock = -1; + pqDropConnection(conn); conn->status = CONNECTION_NEEDED; - /* Discard any unread/unsent data */ - conn->inStart = conn->inCursor = conn->inEnd = 0; - conn->outCount = 0; goto keep_going; } @@ -2323,12 +2319,8 @@ keep_going: /* We will come back to here until there is /* only retry once */ conn->wait_ssl_try = false; /* Must drop the old connection */ - closesocket(conn->sock); - conn->sock = -1; + pqDropConnection(conn); conn->status = CONNECTION_NEEDED; - /* Discard any unread/unsent data */ - conn->inStart = conn->inCursor = conn->inEnd = 0; - conn->outCount = 0; goto keep_going; } @@ -2343,13 +2335,8 @@ keep_going: /* We will come back to here until there is /* only retry once */ conn->allow_ssl_try = false; /* Must drop the old connection */ - pqsecure_close(conn); - closesocket(conn->sock); - conn->sock = -1; + pqDropConnection(conn); conn->status = CONNECTION_NEEDED; - /* Discard any unread/unsent data */ - conn->inStart = conn->inCursor = conn->inEnd = 0; - conn->outCount = 0; goto keep_going; } #endif @@ -2509,13 +2496,8 @@ keep_going: /* We will come back to here until there is PQclear(res); conn->send_appname = false; /* Must drop the old connection */ - pqsecure_close(conn); - closesocket(conn->sock); - conn->sock = -1; + pqDropConnection(conn); conn->status = CONNECTION_NEEDED; - /* Discard any unread/unsent data */ - conn->inStart = conn->inCursor = conn->inEnd = 0; - conn->outCount = 0; goto keep_going; } } @@ -2909,12 +2891,7 @@ closePGconn(PGconn *conn) /* * Close the connection, reset all transient state, flush I/O buffers. */ - if (conn->sock >= 0) - { - pqsecure_close(conn); - closesocket(conn->sock); - } - conn->sock = -1; + pqDropConnection(conn); conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just * absent */ conn->asyncStatus = PGASYNC_IDLE; @@ -2943,8 +2920,6 @@ closePGconn(PGconn *conn) if (conn->lobjfuncs) free(conn->lobjfuncs); conn->lobjfuncs = NULL; - conn->inStart = conn->inCursor = conn->inEnd = 0; - conn->outCount = 0; #ifdef ENABLE_GSS { OM_uint32 min_s; diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index b5e5519c41..0cd0d4288f 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -780,11 +780,8 @@ retry4: * has been set already. */ definitelyFailed: + pqDropConnection(conn); conn->status = CONNECTION_BAD; /* No more connection to backend */ - pqsecure_close(conn); - closesocket(conn->sock); - conn->sock = -1; - return -1; } diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c index d289f82285..c605bcd734 100644 --- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -430,9 +430,7 @@ handleSyncLoss(PGconn *conn, char id, int msgLength) pqSaveErrorResult(conn); conn->asyncStatus = PGASYNC_READY; /* drop out of GetResult wait loop */ - pqsecure_close(conn); - closesocket(conn->sock); - conn->sock = -1; + pqDropConnection(conn); conn->status = CONNECTION_BAD; /* No more connection to backend */ } diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index 2bac59c3d8..4a6c8fedf2 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -488,6 +488,7 @@ extern char *const pgresStatus[]; /* === in fe-connect.c === */ +extern void pqDropConnection(PGconn *conn); extern int pqPacketSend(PGconn *conn, char pack_type, const void *buf, size_t buf_len); extern bool pqGetHomeDirectory(char *buf, int bufsize);