Skip to content

Commit cdfa378

Browse files
committed
Libmodule 4.2.0 with a small behavioral change: avoid starting module as soon as they're registered. Start them (and call their init() callback) just once ctx starts looping. Some small refactoring too.
1 parent e414f50 commit cdfa378

File tree

13 files changed

+77
-45
lines changed

13 files changed

+77
-45
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
cmake_minimum_required (VERSION 3.3.2)
22

3-
project(libmodule VERSION 4.1.0 LANGUAGES C CXX)
3+
project(libmodule VERSION 4.2.0 LANGUAGES C CXX)
44

55
if(NOT CMAKE_BUILD_TYPE)
66
set(CMAKE_BUILD_TYPE Release)

Lib/module.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ static module_ret_code _register_fd(module *mod, const int fd, const bool autocl
104104
tmp->prev = mod->fds;
105105
tmp->self = &mod->self;
106106
mod->fds = tmp;
107-
mod->self.ctx->num_fds++;
108107
/* If a fd is registered at runtime, start polling on it */
109108
int ret = 0;
110109
if (_module_is(mod, RUNNING)) {
@@ -116,7 +115,7 @@ static module_ret_code _register_fd(module *mod, const int fd, const bool autocl
116115
return MOD_ERR;
117116
}
118117

119-
/* Linearly searching for fd */
118+
/* Linear search for fd */
120119
static module_ret_code _deregister_fd(module *mod, const int fd) {
121120
module_poll_t **tmp = &mod->fds;
122121

@@ -134,7 +133,6 @@ static module_ret_code _deregister_fd(module *mod, const int fd) {
134133
}
135134
memhook._free(t->ev);
136135
memhook._free(t);
137-
mod->self.ctx->num_fds--;
138136
return !ret ? MOD_OK : MOD_ERR;
139137
}
140138
tmp = &(*tmp)->prev;
@@ -205,12 +203,12 @@ bool _module_is(const module *mod, const enum module_states st) {
205203
return mod->state & st;
206204
}
207205

208-
209206
int evaluate_module(void *data, void *m) {
210207
module *mod = (module *)m;
211208
if (_module_is(mod, IDLE) && mod->hook.evaluate()) {
212-
mod->hook.init();
213-
start(mod, "Failed to start module.");
209+
if (start(mod, "Failed to start module.") == MOD_OK) {
210+
mod->hook.init();
211+
}
214212
}
215213
return MAP_OK;
216214
}
@@ -272,7 +270,8 @@ module_ret_code module_register(const char *name, const char *ctx_name, const se
272270
memcpy((self_t *)&mod->self, &((self_t){ mod, context, true }), sizeof(self_t));
273271

274272
if (map_put(context->modules, mod->name, mod, false, false) == MAP_OK) {
275-
evaluate_module(NULL, mod);
273+
mod->pubsub_fd[0] = -1;
274+
mod->pubsub_fd[1] = -1;
276275
return MOD_OK;
277276
}
278277
ret = MOD_ERR;
@@ -296,7 +295,7 @@ module_ret_code module_deregister(const self_t **self) {
296295
/* Free all unread pubsub msg for this module */
297296
flush_pubsub_msg(tmp, mod);
298297

299-
stop(mod, "Failed to stop module.", 1);
298+
stop(mod, "Failed to stop module.", true);
300299

301300
/* Remove the module from the context */
302301
map_remove(tmp->ctx->modules, mod->name);

Lib/modules.c

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ static _ctor1_ void modules_init(void);
55
static _dtor0_ void modules_destroy(void);
66
static void evaluate_new_state(m_context *c);
77
static module_ret_code loop_start(m_context *c, const int max_events);
8-
static int recv_events(m_context *c, int timeout);
98
static int loop_stop(m_context *c);
9+
static inline int loop_quit(m_context *c, const uint8_t quit_code);
10+
static int recv_events(m_context *c, int timeout);
1011

1112
map_t *ctx;
1213
memalloc_hook memhook;
@@ -31,14 +32,36 @@ static module_ret_code loop_start(m_context *c, const int max_events) {
3132
c->looping = true;
3233
c->quit_code = 0;
3334
c->max_events = max_events;
34-
35-
/* Tell every module that loop is started */
35+
36+
/* Eventually start any IDLE module */
37+
evaluate_new_state(c);
38+
39+
/* Tell every RUNNING module that loop is started */
3640
tell_system_pubsub_msg(c, LOOP_STARTED, NULL);
3741
return MOD_OK;
3842
}
3943
return MOD_ERR;
4044
}
4145

46+
static int loop_stop(m_context *c) {
47+
/* Tell every module that loop is stopped */
48+
tell_system_pubsub_msg(c, LOOP_STOPPED, NULL);
49+
50+
/* Flush pubsub msg to avoid memleaks */
51+
map_iterate(c->modules, flush_pubsub_msg, NULL);
52+
53+
poll_destroy_pevents(&c->pevents, &c->max_events);
54+
c->looping = false;
55+
c->quit = false;
56+
return c->quit_code;
57+
}
58+
59+
static inline int loop_quit(m_context *c, const uint8_t quit_code) {
60+
c->quit = true;
61+
c->quit_code = quit_code;
62+
return MOD_OK;
63+
}
64+
4265
static int recv_events(m_context *c, int timeout) {
4366
int nfds = poll_wait(c->fd, c->max_events, c->pevents, timeout);
4467
for (int i = 0; i < nfds; i++) {
@@ -84,28 +107,14 @@ static int recv_events(m_context *c, int timeout) {
84107
} else if (nfds < 0) {
85108
if (errno != EINTR && errno != EAGAIN) {
86109
fprintf(stderr, "Module loop error: %s.\n", strerror(errno));
87-
c->quit = true;
88-
c->quit_code = errno;
110+
loop_quit(c, errno);
89111
} else {
90112
nfds = 0; // return < 0 only for real errors
91113
}
92114
}
93115
return nfds;
94116
}
95117

96-
static int loop_stop(m_context *c) {
97-
/* Tell every module that loop is stopped */
98-
tell_system_pubsub_msg(c, LOOP_STOPPED, NULL);
99-
100-
/* Flush pubsub msg to avoid memleaks */
101-
map_iterate(c->modules, flush_pubsub_msg, NULL);
102-
103-
poll_destroy_pevents(&c->pevents, &c->max_events);
104-
c->looping = false;
105-
c->quit = false;
106-
return c->quit_code;
107-
}
108-
109118
/** Public API **/
110119

111120
module_ret_code modules_set_memalloc_hook(const memalloc_hook *hook) {
@@ -135,7 +144,6 @@ module_ret_code modules_ctx_set_logger(const char *ctx_name, const log_cb logger
135144
module_ret_code modules_ctx_loop_events(const char *ctx_name, const int max_events) {
136145
MOD_PARAM_ASSERT(max_events > 0);
137146
FIND_CTX(ctx_name);
138-
MOD_ASSERT(c->num_fds > 0, "No fds to loop on.", MOD_ERR);
139147
MOD_ASSERT(!c->looping, "Context already looping.", MOD_ERR);
140148

141149
if (loop_start(c, max_events) == MOD_OK) {
@@ -151,9 +159,7 @@ module_ret_code modules_ctx_quit(const char *ctx_name, const uint8_t quit_code)
151159
FIND_CTX(ctx_name);
152160
MOD_ASSERT(c->looping, "Context not looping.", MOD_ERR);
153161

154-
c->quit = true;
155-
c->quit_code = quit_code;
156-
return MOD_OK;
162+
return loop_quit(c, quit_code);
157163
}
158164

159165
module_ret_code modules_ctx_get_fd(const char *ctx_name, int *fd) {

Lib/priv.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ struct _context {
103103
uint8_t quit_code;
104104
bool looping;
105105
int fd;
106-
int num_fds;
107106
log_cb logger;
108107
map_t *modules;
109108
void *pevents;

Lib/pubsub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ module_ret_code tell_system_pubsub_msg(m_context *c, enum msg_type type, const c
8282
int flush_pubsub_msg(void *data, void *m) {
8383
module *mod = (module *)m;
8484
pubsub_msg_t *mm = NULL;
85-
85+
8686
while (read(mod->pubsub_fd[0], &mm, sizeof(pubsub_msg_t *)) == sizeof(pubsub_msg_t *)) {
8787
/*
8888
* Actually tell msg ONLY if we are not deregistering module,

Samples/MultiCtx/a.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ static void init(void) {
3636
timerValue.it_value.tv_sec = 1;
3737
timerValue.it_interval.tv_sec = 1;
3838
timerfd_settime(fd, 0, &timerValue, NULL);
39-
m_register_fd(fd, 1, NULL);
39+
m_register_fd(fd, true, NULL);
4040
#endif
4141
}
4242

Samples/MultiCtx/b.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#ifdef __linux__
44
#include <sys/signalfd.h>
55
#include <signal.h>
6+
#include <bits/sigaction.h>
67
#endif
78
#include <unistd.h>
89

@@ -28,14 +29,12 @@ static void module_pre_start(void) {
2829
static void init(void) {
2930
#ifdef __linux__
3031
sigset_t mask;
31-
3232
sigemptyset(&mask);
3333
sigaddset(&mask, SIGINT);
3434
sigaddset(&mask, SIGTERM);
35-
sigprocmask(SIG_BLOCK, &mask, NULL);
3635

37-
int fd = signalfd(-1, &mask, 0);
38-
m_register_fd(fd, 1, NULL);
36+
int fd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
37+
m_register_fd(fd, true, NULL);
3938
#endif
4039
}
4140

@@ -63,7 +62,7 @@ static bool evaluate(void) {
6362

6463
/*
6564
* Destroyer function, called at module unload (at end of program).
66-
* Note that module's FD is automatically closed for you.
65+
* Note that module's FD is automatically closed for you if autoclose is set when registering it.
6766
*/
6867
static void destroy(void) {
6968

Samples/MultiCtx/main.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
#include <module/module.h>
33
#include <pthread.h>
44
#include <stdlib.h>
5+
#ifdef __linux__
6+
#include <signal.h>
7+
#include <bits/sigaction.h>
8+
#endif
59

610
static void *loop(void *param);
711

@@ -17,7 +21,20 @@ static void logger(const self_t *self, const char *fmt, va_list args, const void
1721
}
1822
}
1923

24+
void setup_signals(void) {
25+
#ifdef __linux__
26+
sigset_t mask;
27+
sigemptyset(&mask);
28+
sigaddset(&mask, SIGINT);
29+
sigaddset(&mask, SIGTERM);
30+
sigprocmask(SIG_BLOCK, &mask, NULL);
31+
#endif
32+
}
33+
2034
int main() {
35+
/* Properly block signals (that are received by mod "B" on ctx2) */
36+
setup_signals();
37+
2138
/* Our 2 contexts names */
2239
char *ctx1 = "FirstCtx";
2340
char *ctx2 = "SecondCtx";

TODO.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
## 4.2.0
22

3+
### Generic
4+
- [x] Avoid calling evaluate_module when registering a new module. Call evaluate_module on each module when loop_start() is called.
5+
- [x] Fix default values for pubsub_fd[] for each module
6+
- [x] Update tests (module_start should now be called upon registering)
7+
- [x] Fix MultiCtx sample (signalfd multithread crazyness)
8+
- [x] Update doc (changed behaviours!)
9+
- [x] Drop mcontext -> num_fds
10+
11+
## 4.3.0
12+
313
### Submodules
414
- [ ] SUBMODULE(B, A) calls module_register(B) and module_binds_to(A);
515
- [ ] SUBMODULE SHOULD BE STARTED later (after all MODULES) -> ctor3 (this way it'll support only level 1 submodules though (ie: a submodule cannot have submodules))

docs/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
copyright = '2019, Federico Di Pierro'
2424
author = 'Federico Di Pierro'
2525

26-
version = '4.1.0'
27-
release = '4.1.0'
26+
version = '4.2.0'
27+
release = '4.2.0'
2828

2929
highlight_language = "c"
3030

0 commit comments

Comments
 (0)