mirror of https://github.com/citusdata/citus.git
Handle invalid connection hash entries (#4362)
If MemoryContextAlloc errors out -e.g. during an OOM-, ConnectionHashEntry->connections stays as NULL. With this commit, we add isValid flag to ConnectionHashEntry that should be set to true right after we allocate & initialize ConnectionHashEntry->connections list properly, and we check it before accesing to ConnectionHashEntry->connections.pull/4363/head^2
parent
8c3dd6338e
commit
7f3d1182ed
|
@ -161,6 +161,12 @@ AfterXactConnectionHandling(bool isCommit)
|
||||||
hash_seq_init(&status, ConnectionHash);
|
hash_seq_init(&status, ConnectionHash);
|
||||||
while ((entry = (ConnectionHashEntry *) hash_seq_search(&status)) != 0)
|
while ((entry = (ConnectionHashEntry *) hash_seq_search(&status)) != 0)
|
||||||
{
|
{
|
||||||
|
if (!entry->isValid)
|
||||||
|
{
|
||||||
|
/* skip invalid connection hash entries */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
AfterXactHostConnectionHandling(entry, isCommit);
|
AfterXactHostConnectionHandling(entry, isCommit);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -289,11 +295,24 @@ StartNodeUserDatabaseConnection(uint32 flags, const char *hostname, int32 port,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ConnectionHashEntry *entry = hash_search(ConnectionHash, &key, HASH_ENTER, &found);
|
ConnectionHashEntry *entry = hash_search(ConnectionHash, &key, HASH_ENTER, &found);
|
||||||
if (!found)
|
if (!found || !entry->isValid)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* We are just building hash entry or previously it was left in an
|
||||||
|
* invalid state as we couldn't allocate memory for it.
|
||||||
|
* So initialize entry->connections list here.
|
||||||
|
*/
|
||||||
|
entry->isValid = false;
|
||||||
entry->connections = MemoryContextAlloc(ConnectionContext,
|
entry->connections = MemoryContextAlloc(ConnectionContext,
|
||||||
sizeof(dlist_head));
|
sizeof(dlist_head));
|
||||||
dlist_init(entry->connections);
|
dlist_init(entry->connections);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If MemoryContextAlloc errors out -e.g. during an OOM-, entry->connections
|
||||||
|
* stays as NULL. So entry->isValid should be set to true right after we
|
||||||
|
* initialize entry->connections properly.
|
||||||
|
*/
|
||||||
|
entry->isValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if desired, check whether there's a usable connection */
|
/* if desired, check whether there's a usable connection */
|
||||||
|
@ -449,6 +468,12 @@ CloseAllConnectionsAfterTransaction(void)
|
||||||
hash_seq_init(&status, ConnectionHash);
|
hash_seq_init(&status, ConnectionHash);
|
||||||
while ((entry = (ConnectionHashEntry *) hash_seq_search(&status)) != 0)
|
while ((entry = (ConnectionHashEntry *) hash_seq_search(&status)) != 0)
|
||||||
{
|
{
|
||||||
|
if (!entry->isValid)
|
||||||
|
{
|
||||||
|
/* skip invalid connection hash entries */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
dlist_iter iter;
|
dlist_iter iter;
|
||||||
|
|
||||||
dlist_head *connections = entry->connections;
|
dlist_head *connections = entry->connections;
|
||||||
|
@ -483,7 +508,7 @@ ConnectionAvailableToNode(char *hostName, int nodePort, const char *userName,
|
||||||
ConnectionHashEntry *entry =
|
ConnectionHashEntry *entry =
|
||||||
(ConnectionHashEntry *) hash_search(ConnectionHash, &key, HASH_FIND, &found);
|
(ConnectionHashEntry *) hash_search(ConnectionHash, &key, HASH_FIND, &found);
|
||||||
|
|
||||||
if (!found)
|
if (!found || !entry->isValid)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -509,6 +534,12 @@ CloseNodeConnectionsAfterTransaction(char *nodeName, int nodePort)
|
||||||
hash_seq_init(&status, ConnectionHash);
|
hash_seq_init(&status, ConnectionHash);
|
||||||
while ((entry = (ConnectionHashEntry *) hash_seq_search(&status)) != 0)
|
while ((entry = (ConnectionHashEntry *) hash_seq_search(&status)) != 0)
|
||||||
{
|
{
|
||||||
|
if (!entry->isValid)
|
||||||
|
{
|
||||||
|
/* skip invalid connection hash entries */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
dlist_iter iter;
|
dlist_iter iter;
|
||||||
|
|
||||||
if (strcmp(entry->key.hostname, nodeName) != 0 || entry->key.port != nodePort)
|
if (strcmp(entry->key.hostname, nodeName) != 0 || entry->key.port != nodePort)
|
||||||
|
@ -584,6 +615,12 @@ ShutdownAllConnections(void)
|
||||||
hash_seq_init(&status, ConnectionHash);
|
hash_seq_init(&status, ConnectionHash);
|
||||||
while ((entry = (ConnectionHashEntry *) hash_seq_search(&status)) != NULL)
|
while ((entry = (ConnectionHashEntry *) hash_seq_search(&status)) != NULL)
|
||||||
{
|
{
|
||||||
|
if (!entry->isValid)
|
||||||
|
{
|
||||||
|
/* skip invalid connection hash entries */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
dlist_iter iter;
|
dlist_iter iter;
|
||||||
|
|
||||||
dlist_foreach(iter, entry->connections)
|
dlist_foreach(iter, entry->connections)
|
||||||
|
@ -1194,6 +1231,12 @@ FreeConnParamsHashEntryFields(ConnParamsHashEntry *entry)
|
||||||
static void
|
static void
|
||||||
AfterXactHostConnectionHandling(ConnectionHashEntry *entry, bool isCommit)
|
AfterXactHostConnectionHandling(ConnectionHashEntry *entry, bool isCommit)
|
||||||
{
|
{
|
||||||
|
if (!entry || !entry->isValid)
|
||||||
|
{
|
||||||
|
/* callers only pass valid hash entries but let's be on the safe side */
|
||||||
|
ereport(ERROR, (errmsg("connection hash entry is NULL or invalid")));
|
||||||
|
}
|
||||||
|
|
||||||
dlist_mutable_iter iter;
|
dlist_mutable_iter iter;
|
||||||
int cachedConnectionCount = 0;
|
int cachedConnectionCount = 0;
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,9 @@ typedef struct ConnectionHashEntry
|
||||||
{
|
{
|
||||||
ConnectionHashKey key;
|
ConnectionHashKey key;
|
||||||
dlist_head *connections;
|
dlist_head *connections;
|
||||||
|
|
||||||
|
/* connections list is valid or not */
|
||||||
|
bool isValid;
|
||||||
} ConnectionHashEntry;
|
} ConnectionHashEntry;
|
||||||
|
|
||||||
/* hash entry for cached connection parameters */
|
/* hash entry for cached connection parameters */
|
||||||
|
|
Loading…
Reference in New Issue