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.
This commit is contained in:
parent
dda589c96b
commit
210eb9b743
@ -344,6 +344,28 @@ static void default_threadlock(int acquire);
|
|||||||
pgthreadlock_t pg_g_threadlock = default_threadlock;
|
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
|
* Connecting to a Database
|
||||||
*
|
*
|
||||||
@ -1416,12 +1438,7 @@ connectDBStart(PGconn *conn)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
connect_errReturn:
|
connect_errReturn:
|
||||||
if (conn->sock >= 0)
|
pqDropConnection(conn);
|
||||||
{
|
|
||||||
pqsecure_close(conn);
|
|
||||||
closesocket(conn->sock);
|
|
||||||
conn->sock = -1;
|
|
||||||
}
|
|
||||||
conn->status = CONNECTION_BAD;
|
conn->status = CONNECTION_BAD;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1644,8 +1661,7 @@ keep_going: /* We will come back to here until there is
|
|||||||
{
|
{
|
||||||
if (!connectNoDelay(conn))
|
if (!connectNoDelay(conn))
|
||||||
{
|
{
|
||||||
closesocket(conn->sock);
|
pqDropConnection(conn);
|
||||||
conn->sock = -1;
|
|
||||||
conn->addr_cur = addr_cur->ai_next;
|
conn->addr_cur = addr_cur->ai_next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1655,8 +1671,7 @@ keep_going: /* We will come back to here until there is
|
|||||||
appendPQExpBuffer(&conn->errorMessage,
|
appendPQExpBuffer(&conn->errorMessage,
|
||||||
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
|
libpq_gettext("could not set socket to non-blocking mode: %s\n"),
|
||||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||||
closesocket(conn->sock);
|
pqDropConnection(conn);
|
||||||
conn->sock = -1;
|
|
||||||
conn->addr_cur = addr_cur->ai_next;
|
conn->addr_cur = addr_cur->ai_next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1667,8 +1682,7 @@ keep_going: /* We will come back to here until there is
|
|||||||
appendPQExpBuffer(&conn->errorMessage,
|
appendPQExpBuffer(&conn->errorMessage,
|
||||||
libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
|
libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
|
||||||
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
|
||||||
closesocket(conn->sock);
|
pqDropConnection(conn);
|
||||||
conn->sock = -1;
|
|
||||||
conn->addr_cur = addr_cur->ai_next;
|
conn->addr_cur = addr_cur->ai_next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1715,8 +1729,7 @@ keep_going: /* We will come back to here until there is
|
|||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
closesocket(conn->sock);
|
pqDropConnection(conn);
|
||||||
conn->sock = -1;
|
|
||||||
conn->addr_cur = addr_cur->ai_next;
|
conn->addr_cur = addr_cur->ai_next;
|
||||||
continue;
|
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.
|
* failure and keep going if there are more addresses.
|
||||||
*/
|
*/
|
||||||
connectFailureMessage(conn, SOCK_ERRNO);
|
connectFailureMessage(conn, SOCK_ERRNO);
|
||||||
if (conn->sock >= 0)
|
pqDropConnection(conn);
|
||||||
{
|
|
||||||
closesocket(conn->sock);
|
|
||||||
conn->sock = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try the next address, if any.
|
* Try the next address, if any.
|
||||||
@ -1851,6 +1860,7 @@ keep_going: /* We will come back to here until there is
|
|||||||
* error message.
|
* error message.
|
||||||
*/
|
*/
|
||||||
connectFailureMessage(conn, optval);
|
connectFailureMessage(conn, optval);
|
||||||
|
pqDropConnection(conn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If more addresses remain, keep trying, just as in the
|
* 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->addr_cur->ai_next != NULL)
|
||||||
{
|
{
|
||||||
if (conn->sock >= 0)
|
|
||||||
{
|
|
||||||
closesocket(conn->sock);
|
|
||||||
conn->sock = -1;
|
|
||||||
}
|
|
||||||
conn->addr_cur = conn->addr_cur->ai_next;
|
conn->addr_cur = conn->addr_cur->ai_next;
|
||||||
conn->status = CONNECTION_NEEDED;
|
conn->status = CONNECTION_NEEDED;
|
||||||
goto keep_going;
|
goto keep_going;
|
||||||
@ -2137,12 +2142,8 @@ keep_going: /* We will come back to here until there is
|
|||||||
/* only retry once */
|
/* only retry once */
|
||||||
conn->allow_ssl_try = false;
|
conn->allow_ssl_try = false;
|
||||||
/* Must drop the old connection */
|
/* Must drop the old connection */
|
||||||
closesocket(conn->sock);
|
pqDropConnection(conn);
|
||||||
conn->sock = -1;
|
|
||||||
conn->status = CONNECTION_NEEDED;
|
conn->status = CONNECTION_NEEDED;
|
||||||
/* Discard any unread/unsent data */
|
|
||||||
conn->inStart = conn->inCursor = conn->inEnd = 0;
|
|
||||||
conn->outCount = 0;
|
|
||||||
goto keep_going;
|
goto keep_going;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2252,13 +2253,8 @@ keep_going: /* We will come back to here until there is
|
|||||||
{
|
{
|
||||||
conn->pversion = PG_PROTOCOL(2, 0);
|
conn->pversion = PG_PROTOCOL(2, 0);
|
||||||
/* Must drop the old connection */
|
/* Must drop the old connection */
|
||||||
pqsecure_close(conn);
|
pqDropConnection(conn);
|
||||||
closesocket(conn->sock);
|
|
||||||
conn->sock = -1;
|
|
||||||
conn->status = CONNECTION_NEEDED;
|
conn->status = CONNECTION_NEEDED;
|
||||||
/* Discard any unread/unsent data */
|
|
||||||
conn->inStart = conn->inCursor = conn->inEnd = 0;
|
|
||||||
conn->outCount = 0;
|
|
||||||
goto keep_going;
|
goto keep_going;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2323,12 +2319,8 @@ keep_going: /* We will come back to here until there is
|
|||||||
/* only retry once */
|
/* only retry once */
|
||||||
conn->wait_ssl_try = false;
|
conn->wait_ssl_try = false;
|
||||||
/* Must drop the old connection */
|
/* Must drop the old connection */
|
||||||
closesocket(conn->sock);
|
pqDropConnection(conn);
|
||||||
conn->sock = -1;
|
|
||||||
conn->status = CONNECTION_NEEDED;
|
conn->status = CONNECTION_NEEDED;
|
||||||
/* Discard any unread/unsent data */
|
|
||||||
conn->inStart = conn->inCursor = conn->inEnd = 0;
|
|
||||||
conn->outCount = 0;
|
|
||||||
goto keep_going;
|
goto keep_going;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2343,13 +2335,8 @@ keep_going: /* We will come back to here until there is
|
|||||||
/* only retry once */
|
/* only retry once */
|
||||||
conn->allow_ssl_try = false;
|
conn->allow_ssl_try = false;
|
||||||
/* Must drop the old connection */
|
/* Must drop the old connection */
|
||||||
pqsecure_close(conn);
|
pqDropConnection(conn);
|
||||||
closesocket(conn->sock);
|
|
||||||
conn->sock = -1;
|
|
||||||
conn->status = CONNECTION_NEEDED;
|
conn->status = CONNECTION_NEEDED;
|
||||||
/* Discard any unread/unsent data */
|
|
||||||
conn->inStart = conn->inCursor = conn->inEnd = 0;
|
|
||||||
conn->outCount = 0;
|
|
||||||
goto keep_going;
|
goto keep_going;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -2509,13 +2496,8 @@ keep_going: /* We will come back to here until there is
|
|||||||
PQclear(res);
|
PQclear(res);
|
||||||
conn->send_appname = false;
|
conn->send_appname = false;
|
||||||
/* Must drop the old connection */
|
/* Must drop the old connection */
|
||||||
pqsecure_close(conn);
|
pqDropConnection(conn);
|
||||||
closesocket(conn->sock);
|
|
||||||
conn->sock = -1;
|
|
||||||
conn->status = CONNECTION_NEEDED;
|
conn->status = CONNECTION_NEEDED;
|
||||||
/* Discard any unread/unsent data */
|
|
||||||
conn->inStart = conn->inCursor = conn->inEnd = 0;
|
|
||||||
conn->outCount = 0;
|
|
||||||
goto keep_going;
|
goto keep_going;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2909,12 +2891,7 @@ closePGconn(PGconn *conn)
|
|||||||
/*
|
/*
|
||||||
* Close the connection, reset all transient state, flush I/O buffers.
|
* Close the connection, reset all transient state, flush I/O buffers.
|
||||||
*/
|
*/
|
||||||
if (conn->sock >= 0)
|
pqDropConnection(conn);
|
||||||
{
|
|
||||||
pqsecure_close(conn);
|
|
||||||
closesocket(conn->sock);
|
|
||||||
}
|
|
||||||
conn->sock = -1;
|
|
||||||
conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just
|
conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just
|
||||||
* absent */
|
* absent */
|
||||||
conn->asyncStatus = PGASYNC_IDLE;
|
conn->asyncStatus = PGASYNC_IDLE;
|
||||||
@ -2943,8 +2920,6 @@ closePGconn(PGconn *conn)
|
|||||||
if (conn->lobjfuncs)
|
if (conn->lobjfuncs)
|
||||||
free(conn->lobjfuncs);
|
free(conn->lobjfuncs);
|
||||||
conn->lobjfuncs = NULL;
|
conn->lobjfuncs = NULL;
|
||||||
conn->inStart = conn->inCursor = conn->inEnd = 0;
|
|
||||||
conn->outCount = 0;
|
|
||||||
#ifdef ENABLE_GSS
|
#ifdef ENABLE_GSS
|
||||||
{
|
{
|
||||||
OM_uint32 min_s;
|
OM_uint32 min_s;
|
||||||
|
@ -780,11 +780,8 @@ retry4:
|
|||||||
* has been set already.
|
* has been set already.
|
||||||
*/
|
*/
|
||||||
definitelyFailed:
|
definitelyFailed:
|
||||||
|
pqDropConnection(conn);
|
||||||
conn->status = CONNECTION_BAD; /* No more connection to backend */
|
conn->status = CONNECTION_BAD; /* No more connection to backend */
|
||||||
pqsecure_close(conn);
|
|
||||||
closesocket(conn->sock);
|
|
||||||
conn->sock = -1;
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,9 +430,7 @@ handleSyncLoss(PGconn *conn, char id, int msgLength)
|
|||||||
pqSaveErrorResult(conn);
|
pqSaveErrorResult(conn);
|
||||||
conn->asyncStatus = PGASYNC_READY; /* drop out of GetResult wait loop */
|
conn->asyncStatus = PGASYNC_READY; /* drop out of GetResult wait loop */
|
||||||
|
|
||||||
pqsecure_close(conn);
|
pqDropConnection(conn);
|
||||||
closesocket(conn->sock);
|
|
||||||
conn->sock = -1;
|
|
||||||
conn->status = CONNECTION_BAD; /* No more connection to backend */
|
conn->status = CONNECTION_BAD; /* No more connection to backend */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,6 +488,7 @@ extern char *const pgresStatus[];
|
|||||||
|
|
||||||
/* === in fe-connect.c === */
|
/* === in fe-connect.c === */
|
||||||
|
|
||||||
|
extern void pqDropConnection(PGconn *conn);
|
||||||
extern int pqPacketSend(PGconn *conn, char pack_type,
|
extern int pqPacketSend(PGconn *conn, char pack_type,
|
||||||
const void *buf, size_t buf_len);
|
const void *buf, size_t buf_len);
|
||||||
extern bool pqGetHomeDirectory(char *buf, int bufsize);
|
extern bool pqGetHomeDirectory(char *buf, int bufsize);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user