PG-1349 Fix deadlock

PG-1349-deadlock
Artem Gavrilov 2025-02-18 12:31:24 +02:00
parent fd43b75153
commit ec1d449dc5
1 changed files with 113 additions and 91 deletions

View File

@ -1968,6 +1968,10 @@ pgsm_store(pgsmEntry *entry)
* we need to create the entry. * we need to create the entry.
*/ */
LWLockAcquire(pgsm->lock, LW_SHARED); LWLockAcquire(pgsm->lock, LW_SHARED);
PG_TRY();
{
shared_hash_entry = (pgsmEntry *) pgsm_hash_find(get_pgsmHash(), &entry->key, &found); shared_hash_entry = (pgsmEntry *) pgsm_hash_find(get_pgsmHash(), &entry->key, &found);
if (!shared_hash_entry) if (!shared_hash_entry)
@ -1990,12 +1994,13 @@ pgsm_store(pgsmEntry *entry)
} }
/* /*
* Get the memory address from DSA pointer and copy the query text in * Get the memory address from DSA pointer and copy the query text
* local variable * in local variable
*/ */
query_buff = dsa_get_address(query_dsa_area, dsa_query_pointer); query_buff = dsa_get_address(query_dsa_area, dsa_query_pointer);
memcpy(query_buff, query, query_len); memcpy(query_buff, query, query_len);
/* Promotion to exclusive lock */
LWLockRelease(pgsm->lock); LWLockRelease(pgsm->lock);
LWLockAcquire(pgsm->lock, LW_EXCLUSIVE); LWLockAcquire(pgsm->lock, LW_EXCLUSIVE);
@ -2008,8 +2013,6 @@ pgsm_store(pgsmEntry *entry)
} }
PG_CATCH(); PG_CATCH();
{ {
LWLockRelease(pgsm->lock);
if (DsaPointerIsValid(dsa_query_pointer)) if (DsaPointerIsValid(dsa_query_pointer))
dsa_free(query_dsa_area, dsa_query_pointer); dsa_free(query_dsa_area, dsa_query_pointer);
PG_RE_THROW(); PG_RE_THROW();
@ -2019,14 +2022,13 @@ pgsm_store(pgsmEntry *entry)
if (shared_hash_entry == NULL) if (shared_hash_entry == NULL)
{ {
LWLockRelease(pgsm->lock);
if (DsaPointerIsValid(dsa_query_pointer)) if (DsaPointerIsValid(dsa_query_pointer))
dsa_free(query_dsa_area, dsa_query_pointer); dsa_free(query_dsa_area, dsa_query_pointer);
/* /*
* Out of memory; report only if the state has changed now. * Out of memory; report only if the state has changed now.
* Otherwise we risk filling up the log file with these message. * Otherwise we risk filling up the log file with these
* message.
*/ */
if (!IsSystemOOM()) if (!IsSystemOOM())
{ {
@ -2042,6 +2044,8 @@ pgsm_store(pgsmEntry *entry)
} PGSM_END_DISABLE_ERROR_CAPTURE(); } PGSM_END_DISABLE_ERROR_CAPTURE();
} }
LWLockRelease(pgsm->lock);
return; return;
} }
else else
@ -2082,6 +2086,24 @@ pgsm_store(pgsmEntry *entry)
PGSM_STORE); PGSM_STORE);
memset(&entry->counters, 0, sizeof(entry->counters)); memset(&entry->counters, 0, sizeof(entry->counters));
}
PG_CATCH();
{
/*
* Force LWLock release in case of error because we need to aquire it
* again in pgsm_emit_log_hook
*
* On ereport with level >= ERROR Postgres resets
* InterruptHoldoffCount counter (see errfinish funcion in elog.c). We
* need to increment it to be able to release lock here.
*/
HOLD_INTERRUPTS(); /* Increments holdoff counter */
LWLockRelease(pgsm->lock); /* Decrements holdoff counter */
PG_RE_THROW();
}
PG_END_TRY();
LWLockRelease(pgsm->lock); LWLockRelease(pgsm->lock);
} }