Skip to content

Commit 4fad1e7

Browse files
committed
module: reference count modules in tree
- module is now removed when reach ref=0 - childer now hold reference to parent As a consequence, if parent is (mistakenly) removed before child, the poiner to it doesn't need to be erased, which is bug-prone (other thread might have already retrieved the parent pointer).
1 parent c218188 commit 4fad1e7

File tree

2 files changed

+17
-15
lines changed

2 files changed

+17
-15
lines changed

src/module.c

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ void module_register(struct module *module_data, struct module *parent)
9898
struct module_priv_state *module_priv = calloc(1, sizeof *module_data->module_priv);
9999
module_data->module_priv = module_priv;
100100
module_priv->magic = MODULE_MAGIC;
101+
module_priv->ref = 1;
101102
memcpy(&module_priv->wrapper, module_data, sizeof *module_data);
102103

103104
int ret = 0;
@@ -122,35 +123,31 @@ void module_register(struct module *module_data, struct module *parent)
122123
module_mutex_lock(&parent->module_priv->lock);
123124
simple_linked_list_append(parent->module_priv->children, module_priv);
124125
module_check_undelivered_messages(parent);
126+
module_priv->parent->ref += 1;
125127
module_mutex_unlock(&parent->module_priv->lock);
126128
}
127129

128-
static void
130+
static bool
129131
module_del_ref(struct module_priv_state *module_priv)
130132
{
131133
assert(module_priv->magic == MODULE_MAGIC);
132134

135+
module_mutex_lock(&module_priv->lock);
136+
const int new_ref = module_priv->ref -= 1;
137+
module_mutex_unlock(&module_priv->lock);
138+
if (new_ref > 0) {
139+
return false;
140+
}
141+
133142
if(module_priv->parent) {
134143
module_mutex_lock(&module_priv->parent->lock);
135144
bool found = simple_linked_list_remove(
136145
module_priv->parent->children, module_priv);
137146
assert(found);
138147
module_mutex_unlock(&module_priv->parent->lock);
148+
module_del_ref(module_priv->parent);
139149
}
140150

141-
if(simple_linked_list_size(module_priv->children) > 0) {
142-
log_msg(LOG_LEVEL_WARNING, "Warning: Child database not empty! Remaining:\n");
143-
dump_tree(&module_priv->wrapper, 0);
144-
module_mutex_lock(&module_priv->lock);
145-
for(void *it = simple_linked_list_it_init(module_priv->children); it != NULL; ) {
146-
struct module_priv_state *child = simple_linked_list_it_next(&it);
147-
assert(child->magic == MODULE_MAGIC);
148-
module_mutex_lock(&child->lock);
149-
child->parent = NULL;
150-
module_mutex_unlock(&child->lock);
151-
}
152-
module_mutex_unlock(&module_priv->lock);
153-
}
154151
simple_linked_list_destroy(module_priv->children);
155152

156153
if(simple_linked_list_size(module_priv->msg_queue) > 0) {
@@ -174,6 +171,7 @@ module_del_ref(struct module_priv_state *module_priv)
174171

175172
pthread_mutex_destroy(&module_priv->lock);
176173
free(module_priv);
174+
return true;
177175
}
178176

179177
void
@@ -187,7 +185,10 @@ module_done(struct module *module_data)
187185
return;
188186
}
189187
struct module_priv_state *module_priv = module_data->module_priv;
190-
module_del_ref(module_priv);
188+
if (!module_del_ref(module_priv)) {
189+
log_msg(LOG_LEVEL_WARNING, "Warning: Child database not empty! Remaining:\n");
190+
dump_tree(&module_priv->wrapper, 0);
191+
}
191192
module_data->module_priv = NULL; // to avoid multiple deinit
192193
}
193194

src/module.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ struct module_priv_state {
118118
uint32_t magic;
119119
struct module wrapper;
120120
pthread_mutex_t lock;
121+
int ref; ///< reference count
121122
struct module_priv_state *parent;
122123
struct simple_linked_list *children; // module_priv_state
123124

0 commit comments

Comments
 (0)