mirror of
https://github.com/percona/pg_stat_monitor.git
synced 2026-02-04 05:56:21 +00:00
PG-244: Fix race condition in get_next_wbucket().
The if condition bellow in geta_next_wbucket() was subject to a race condition: if ((current_usec - pgss->prev_bucket_usec) > (PGSM_BUCKET_TIME * 1000 * 1000)) Two or more threads/processes could easily evaluate this condition to true, thus executing more than once the block that would calculate a new bucket id, clear/move old entries in the pgss_query_hash and pgss_hash hash tables. To avoid this problem, we define prev_bucket_usec and current_wbucket variables as atomic and execute a loop to check if another thread has updated prev_bucket_usec before the current one.
This commit is contained in:
20
hash_query.c
20
hash_query.c
@@ -146,7 +146,7 @@ hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key, int encoding)
|
||||
entry = (pgssEntry *) hash_search(pgss_hash, key, HASH_ENTER_NULL, &found);
|
||||
if (!found)
|
||||
{
|
||||
pgss->bucket_entry[pgss->current_wbucket]++;
|
||||
pgss->bucket_entry[pg_atomic_read_u64(&pgss->current_wbucket)]++;
|
||||
/* New entry, initialize it */
|
||||
/* reset the statistics */
|
||||
memset(&entry->counters, 0, sizeof(Counters));
|
||||
@@ -236,22 +236,6 @@ hash_entry_dealloc(int new_bucket_id, int old_bucket_id)
|
||||
pgssEntry *entry = NULL;
|
||||
List *pending_entries = NIL;
|
||||
ListCell *pending_entry;
|
||||
|
||||
/*
|
||||
* During transition to a new bucket id, a rare but possible race
|
||||
* condition may happen while reading pgss->current_wbucket. If a
|
||||
* different thread/process updates pgss->current_wbucket before this
|
||||
* function is called, it may happen that old_bucket_id == new_bucket_id.
|
||||
* If that is the case, we adjust the old bucket id here instead of using
|
||||
* a lock in order to avoid the overhead.
|
||||
*/
|
||||
if (old_bucket_id != -1 && old_bucket_id == new_bucket_id)
|
||||
{
|
||||
if (old_bucket_id == 0)
|
||||
old_bucket_id = PGSM_MAX_BUCKETS - 1;
|
||||
else
|
||||
old_bucket_id--;
|
||||
}
|
||||
|
||||
hash_seq_init(&hash_seq, pgss_hash);
|
||||
while ((entry = hash_seq_search(&hash_seq)) != NULL)
|
||||
@@ -344,7 +328,7 @@ hash_entry_reset()
|
||||
{
|
||||
hash_search(pgss_hash, &entry->key, HASH_REMOVE, NULL);
|
||||
}
|
||||
pgss->current_wbucket = 0;
|
||||
pg_atomic_write_u64(&pgss->current_wbucket, 0);
|
||||
LWLockRelease(pgss->lock);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user