Skip to content

Commit 4d74942

Browse files
committed
Properly honor current module's callback when flushing pubsub messages.
1 parent 3b64d0f commit 4d74942

File tree

7 files changed

+41
-36
lines changed

7 files changed

+41
-36
lines changed

Lib/module.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ module_ret_code module_register(const char *name, const char *ctx_name, const se
243243
break;
244244
}
245245

246-
mod->hook = *hook;
246+
memcpy(&mod->hook, hook, sizeof(userhook));
247247
mod->state = IDLE;
248248
mod->fds = NULL;
249249

Lib/modules.c

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,7 @@ module_ret_code modules_set_memalloc_hook(const memalloc_hook *hook) {
3131
MOD_ASSERT(hook->_realloc, "NULL realloc fn.", MOD_ERR);
3232
MOD_ASSERT(hook->_calloc, "NULL calloc fn.", MOD_ERR);
3333
MOD_ASSERT(hook->_free, "NULL free fn.", MOD_ERR);
34-
35-
memhook._malloc = hook->_malloc;
36-
memhook._realloc = hook->_realloc;
37-
memhook._calloc = hook->_calloc;
38-
memhook._free = hook->_free;
34+
memcpy(&memhook, hook, sizeof(memalloc_hook));
3935
} else {
4036
memhook._malloc = malloc;
4137
memhook._realloc = realloc;
@@ -94,13 +90,7 @@ module_ret_code modules_ctx_loop_events(const char *ctx_name, const int max_even
9490
}
9591

9692
if (!msg.is_pubsub || msg.pubsub_msg) {
97-
/* If module is using some different receive function, honor it. */
98-
recv_cb cb = stack_peek(mod->recvs);
99-
if (!cb) {
100-
/* Fallback to module default receive */
101-
cb = mod->hook.recv;
102-
}
103-
cb(&msg, mod->userdata);
93+
run_pubsub_cb(mod, &msg);
10494

10595
/* Properly free pubsub msg */
10696
if (msg.is_pubsub) {
@@ -127,9 +117,10 @@ module_ret_code modules_ctx_loop_events(const char *ctx_name, const int max_even
127117

128118
/* Tell every module that loop is stopped */
129119
tell_system_pubsub_msg(c, LOOP_STOPPED, NULL);
130-
120+
131121
/* Flush pubsub msg to avoid memleaks */
132122
map_iterate(c->modules, flush_pubsub_msg, NULL);
123+
133124
poll_destroy_pevents(&c->pevents, &c->max_events);
134125
c->looping = false;
135126
return c->quit_code;
@@ -139,12 +130,9 @@ module_ret_code modules_ctx_loop_events(const char *ctx_name, const int max_even
139130

140131
module_ret_code modules_ctx_quit(const char *ctx_name, const uint8_t quit_code) {
141132
FIND_CTX(ctx_name);
142-
143-
if (c->looping) {
144-
c->quit = true;
145-
c->quit_code = quit_code;
146-
return MOD_OK;
147-
}
148-
MODULE_DEBUG("Context not looping.\n");
149-
return MOD_ERR;
133+
MOD_ASSERT(c->looping, "Context not looping.", MOD_ERR);
134+
135+
c->quit = true;
136+
c->quit_code = quit_code;
137+
return MOD_OK;
150138
}

Lib/priv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#pragma once
2+
13
#include <stdlib.h>
24
#include "map.h"
35
#include "stack.h"
@@ -113,6 +115,7 @@ int evaluate_module(void *data, void *m);
113115
module_ret_code tell_system_pubsub_msg(m_context *c, enum msg_type type, const char *topic);
114116
int flush_pubsub_msg(void *data, void *m);
115117
void destroy_pubsub_msg(pubsub_msg_t *m);
118+
void run_pubsub_cb(module *mod, const msg_t *msg);
116119

117120
/* Defined in priv.c */
118121
char *mem_strdup(const char *s);

Lib/pubsub.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ int flush_pubsub_msg(void *data, void *m) {
8585
*/
8686
if (!data) {
8787
MODULE_DEBUG("Flushing pubsub message for module '%s'.\n", mod->name);
88-
const msg_t msg = { .is_pubsub = 1, .pubsub_msg = mm };
89-
mod->hook.recv(&msg, mod->userdata);
88+
const msg_t msg = { .is_pubsub = true, .pubsub_msg = mm };
89+
run_pubsub_cb(mod, &msg);
9090
}
9191
destroy_pubsub_msg(mm);
9292
}
@@ -98,6 +98,17 @@ void destroy_pubsub_msg(pubsub_msg_t *m) {
9898
memhook._free(m);
9999
}
100100

101+
102+
void run_pubsub_cb(module *mod, const msg_t *msg) {
103+
/* If module is using some different receive function, honor it. */
104+
recv_cb cb = stack_peek(mod->recvs);
105+
if (!cb) {
106+
/* Fallback to module default receive */
107+
cb = mod->hook.recv;
108+
}
109+
cb(msg, mod->userdata);
110+
}
111+
101112
/** Public API **/
102113

103114
module_ret_code module_ref(const self_t *self, const char *name, const self_t **modref) {

TODO.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ module_ref should then return a new self_t* object, add it to a stack in module.
4242
- [x] Fix issue in map_new if m->data calloc fails: map object was not memsetted to 0; it would lead to a crash when map_free was called
4343
- [x] Update doc!
4444

45+
### Fix
46+
- [x] Actually honor current module's callback when flushing pubsub messages
47+
4548
### Examples
4649
- [x] Update examples!
4750

docs/src/lifecycle.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
<br />
44

5-
Module Lifecycle
6-
================
5+
Lifecycle
6+
=========
77

88
Easy API
99
--------

docs/src/pubsub.rst

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22

33
<br />
44

5-
PubSub interface
6-
================
5+
PubSub
6+
======
77

8-
PubSub concept
9-
--------------
8+
Concepts
9+
--------
1010

1111
Those unfamiliar with actor like messaging, may wonder what a pubsub messaging is. |br|
1212
PubSub (Publisher-Subscriber) messaging is much like a producer/consumer architecture: an entity registers a "topic" on which it will send messages. |br|
1313
Other entities can then subscribe to the topic to receive those messages. |br|
1414

15-
PubSub implementation
16-
---------------------
15+
Implementation
16+
--------------
1717

1818
Since libmodule 2.1, pubsub implementation is async and makes use of unix pipes. |br|
1919
When sending a message to other modules, a pubsub message is allocated and its address is written in recipient module's writable end of pipe. |br|
@@ -23,15 +23,15 @@ Since libmodule 4.0.0, module_tell() makes use of module references: it means re
2323
Note that you cannot call any function on a module's reference as you cannot impersonate another module. |br|
2424
Only module_is(), module_get_name/context() functions can be called passing as self_t handler a module's reference.
2525

26-
PubSub system messages
27-
----------------------
26+
System messages
27+
---------------
2828

2929
Beside USER messages (pubsub_msg_t.type), there are 4 system messages, with type respectively: LOOP_STARTED, LOOP_STOPPED, TOPIC_REGISTERED, TOPIC_DEREGISTERED. |br|
3030
These pubsub messages are automatically sent by libmodule (note that sender will be NULL) when matching functions are called. |br|
3131
For example, you can use TOPIC_REGISTERED message (note that pubsub_msg_t.topic will be valued matching newly created topic) to subscribe to a topic as soon as it appears in current context.
3232

33-
PubSub notes
34-
------------
33+
Notes
34+
-----
3535

3636
Note that a context must be looping to receive any pubsub message. |br|
3737
Moreover, when a context stops looping, all pubsub messages will be flushed and thus delivered to each RUNNING module. |br|

0 commit comments

Comments
 (0)