shared/unit-file: make sure the old hashmaps and sets are freed upon replacement

Possibly fixes #15220. (There might be another leak. I'm still investigating.)

The leak would occur when the path cache was rebuilt. So in normal circumstances
it wouldn't be too bad, since usually the path cache is not rebuilt too often. But
the case in #15220, where new unit files are created in a loop and started, the leak
occurs once for each unit file:

$ for i in {1..300}; do cp ~/.config/systemd/user/test0001.service ~/.config/systemd/user/test$(printf %04d $i).service; systemctl --user start test$(printf %04d $i).service;done
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2020-05-28 18:51:52 +02:00
parent db868d45f9
commit 3fb2326f3e
6 changed files with 33 additions and 12 deletions
+2
View File
@@ -55,6 +55,8 @@ void path_hash_func(const char *q, struct siphash *state) {
}
DEFINE_HASH_OPS(path_hash_ops, char, path_hash_func, path_compare);
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(path_hash_ops_free,
char, path_hash_func, path_compare, free);
void trivial_hash_func(const void *p, struct siphash *state) {
siphash24_compress(&p, sizeof(p), state);
+1
View File
@@ -81,6 +81,7 @@ extern const struct hash_ops string_hash_ops_free_free;
void path_hash_func(const char *p, struct siphash *state);
extern const struct hash_ops path_hash_ops;
extern const struct hash_ops path_hash_ops_free;
/* This will compare the passed pointers directly, and will not dereference them. This is hence not useful for strings
* or suchlike. */
+8
View File
@@ -89,6 +89,14 @@ OrderedHashmap *internal_ordered_hashmap_new(const struct hash_ops *hash_ops HA
#define hashmap_new(ops) internal_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
#define ordered_hashmap_new(ops) internal_ordered_hashmap_new(ops HASHMAP_DEBUG_SRC_ARGS)
#define hashmap_free_and_replace(a, b) \
({ \
hashmap_free(a); \
(a) = (b); \
(b) = NULL; \
0; \
})
HashmapBase *internal_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value);
static inline Hashmap *hashmap_free(Hashmap *h) {
return (void*) internal_hashmap_free(HASHMAP_BASE(h), NULL, NULL);
+8
View File
@@ -5,6 +5,14 @@
#include "hashmap.h"
#include "macro.h"
#define set_free_and_replace(a, b) \
({ \
set_free(a); \
(a) = (b); \
(b) = NULL; \
0; \
})
Set *internal_set_new(const struct hash_ops *hash_ops HASHMAP_DEBUG_PARAMS);
#define set_new(ops) internal_set_new(ops HASHMAP_DEBUG_SRC_ARGS)