Add ShutdownConnection() which cancels statement before closing connection.

That's primarily useful in error cases, where we want to make sure
locks etc held by commands running on workers are released promptly.
pull/1473/head
Andres Freund 2017-06-30 18:20:54 -07:00
parent 75a7ddea0d
commit 24153fae5d
2 changed files with 35 additions and 0 deletions

View File

@ -401,6 +401,40 @@ CloseConnectionByPGconn(PGconn *pqConn)
}
/*
* ShutdownConnection, if necessary cancels the currently running statement,
* and then closes the underlying libpq connection. The MultiConnection
* itself is left intact.
*
* NB: Cancelling a statement requires network IO, and currently is not
* interruptible. Unfortunately libpq does not provide a non-blocking
* implementation of PQcancel(), so we don't have much choice for now.
*/
void
ShutdownConnection(MultiConnection *connection)
{
/*
* Only cancel statement if there's currently one running, and the
* connection is in an OK state.
*/
if (PQstatus(connection->pgConn) == CONNECTION_OK &&
PQtransactionStatus(connection->pgConn) == PQTRANS_ACTIVE)
{
char errorMessage[256] = { 0 };
PGcancel *cancel = PQgetCancel(connection->pgConn);
if (!PQcancel(cancel, errorMessage, sizeof(errorMessage)))
{
ereport(WARNING, (errmsg("could not cancel connection: %s",
errorMessage)));
}
PQfreeCancel(cancel);
}
PQfinish(connection->pgConn);
connection->pgConn = NULL;
}
/*
* FinishConnectionListEstablishment is a wrapper around FinishConnectionEstablishment.
* The function iterates over the multiConnectionList and finishes the connection

View File

@ -134,6 +134,7 @@ extern MultiConnection * GetConnectionFromPGconn(struct pg_conn *pqConn);
extern void CloseNodeConnectionsAfterTransaction(char *nodeName, int nodePort);
extern void CloseConnection(MultiConnection *connection);
extern void CloseConnectionByPGconn(struct pg_conn *pqConn);
extern void ShutdownConnection(MultiConnection *connection);
/* dealing with a connection */
extern void FinishConnectionListEstablishment(List *multiConnectionList);