summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2020-09-12 00:09:07 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-09-12 14:16:19 +0200
commite662cf6d515daad19e70c3d85e244b213ac48997 (patch)
treefa63b427b5d3363781b56531e6ba3490faeb0585
parentda310c6b45aa6ac360d2fc336eb164e401c08a86 (diff)
downloadsystemd-e662cf6d515daad19e70c3d85e244b213ac48997.tar.gz
hashmap: make sure to initialize shared hash key atomically
if we allocate a bunch of hash tables all at the same time, with none earlier than the other, there's a good chance we'll initialize the shared hash key multiple times, so that some threads will see a different shared hash key than others. Let's fix that, and make sure really everyone sees the same hash key. Fixes: #17007 (cherry picked from commit ae0b700a856c0ae460d271bb50dccfaae84dbcab)
-rw-r--r--src/basic/hashmap.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c
index 67c4391230..a4eeb110ee 100644
--- a/src/basic/hashmap.c
+++ b/src/basic/hashmap.c
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
+#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
@@ -19,7 +20,6 @@
#include "strv.h"
#if ENABLE_DEBUG_HASHMAP
-#include <pthread.h>
#include "list.h"
#endif
@@ -189,7 +189,6 @@ assert_cc(DIRECT_BUCKETS(struct set_entry) < (1 << 3));
* a handful of directly stored entries in a hashmap. When a hashmap
* outgrows direct storage, it gets its own key for indirect storage. */
static uint8_t shared_hash_key[HASH_KEY_SIZE];
-static bool shared_hash_key_initialized;
/* Fields that all hashmap/set types must have */
struct HashmapBase {
@@ -768,6 +767,10 @@ static void reset_direct_storage(HashmapBase *h) {
memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
}
+static void shared_hash_key_initialize(void) {
+ random_bytes(shared_hash_key, sizeof(shared_hash_key));
+}
+
static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
HashmapBase *h;
const struct hashmap_type_info *hi = &hashmap_type_info[type];
@@ -790,10 +793,8 @@ static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enu
reset_direct_storage(h);
- if (!shared_hash_key_initialized) {
- random_bytes(shared_hash_key, sizeof(shared_hash_key));
- shared_hash_key_initialized= true;
- }
+ static pthread_once_t once = PTHREAD_ONCE_INIT;
+ assert_se(pthread_once(&once, shared_hash_key_initialize) == 0);
#if ENABLE_DEBUG_HASHMAP
h->debug.func = func;