2 * Copyright 2011 Red Hat, Inc.
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 #define _GNU_SOURCE /* For asprintf() */
35 #include <sys/types.h>
42 #include <verto-module.h>
46 #define __str(s) _str(s)
48 /* Remove flags we can emulate */
49 #define make_actual(flags) ((flags) & ~(VERTO_EV_FLAG_PERSIST|VERTO_EV_FLAG_IO_CLOSE_FD))
54 const verto_module *module;
62 verto_proc_status status;
74 verto_callback *callback;
75 verto_callback *onfree;
90 typedef struct module_record module_record;
91 struct module_record {
93 const verto_module *module;
100 #ifdef BUILTIN_MODULE
101 #define _MODTABLE(n) verto_module_table_ ## n
102 #define MODTABLE(n) _MODTABLE(n)
104 * This symbol can be used when embedding verto.c in a library along with a
105 * built-in private module, to preload the module instead of dynamically
106 * linking it in later. Define to verto_module_table_<modulename>.
108 extern verto_module MODTABLE(BUILTIN_MODULE);
109 static module_record builtin_record = {
110 NULL, &MODTABLE(BUILTIN_MODULE), NULL, "", NULL
112 static module_record *loaded_modules = &builtin_record;
114 static module_record *loaded_modules;
117 static void *(*resize_cb)(void *mem, size_t size);
118 static int resize_cb_hierarchical;
121 static pthread_mutex_t loaded_modules_mutex = PTHREAD_MUTEX_INITIALIZER;
122 #define mutex_lock(x) pthread_mutex_lock(x)
123 #define mutex_unlock(x) pthread_mutex_unlock(x)
125 #define mutex_lock(x)
126 #define mutex_unlock(x)
129 #define vfree(mem) vresize(mem, 0)
131 vresize(void *mem, size_t size)
134 resize_cb = &realloc;
135 return (*resize_cb)(mem, size);
138 #ifndef BUILTIN_MODULE
140 int_vasprintf(char **strp, const char *fmt, va_list ap) {
145 size = vsnprintf(NULL, 0, fmt, apc);
148 if (size <= 0 || !(*strp = malloc(size + 1)))
151 return vsnprintf(*strp, size + 1, fmt, ap);
155 int_asprintf(char **strp, const char *fmt, ...) {
160 size = int_vasprintf(strp, fmt, ap);
166 int_get_table_name_from_filename(const char *filename)
168 char *bn = NULL, *tmp = NULL;
173 tmp = strdup(filename);
184 tmp = strchr(bn, '-');
186 if (strchr(tmp+1, '.')) {
187 *strchr(tmp+1, '.') = '\0';
188 if (int_asprintf(&tmp, "%s%s", __str(VERTO_MODULE_TABLE()), tmp + 1) < 0)
200 verto_ev_type reqtypes;
204 shouldload(void *symb, void *misc, char **err)
206 verto_module *table = (verto_module*) symb;
207 shouldload_data *data = (shouldload_data*) misc;
209 /* Make sure we have the proper version */
210 if (table->vers != VERTO_MODULE_VERSION) {
212 *err = strdup("Invalid module version!");
216 /* Check to make sure that we have our required symbol if reqsym == true */
217 if (table->symb && data->reqsym
218 && !module_symbol_is_present(NULL, table->symb)) {
220 int_asprintf(err, "Symbol not found: %s!", table->symb);
224 /* Check to make sure that this module supports our required features */
225 if (data->reqtypes != VERTO_EV_TYPE_NONE
226 && (table->types & data->reqtypes) != data->reqtypes) {
228 *err = strdup("Module does not support required features!");
236 do_load_file(const char *filename, int reqsym, verto_ev_type reqtypes,
237 module_record **record)
239 char *tblname = NULL, *error = NULL;
241 shouldload_data data = { reqsym, reqtypes };
243 /* Check the loaded modules to see if we already loaded one */
244 mutex_lock(&loaded_modules_mutex);
245 for (*record = loaded_modules ; *record ; *record = (*record)->next) {
246 if (!strcmp((*record)->filename, filename)) {
247 mutex_unlock(&loaded_modules_mutex);
251 mutex_unlock(&loaded_modules_mutex);
253 /* Create our module record */
254 tmp = *record = vresize(NULL, sizeof(module_record));
257 memset(tmp, 0, sizeof(module_record));
258 tmp->filename = strdup(filename);
259 if (!tmp->filename) {
264 /* Get the name of the module struct in the library */
265 tblname = int_get_table_name_from_filename(filename);
272 /* Load the module */
273 error = module_load(filename, tblname, shouldload, &data, &tmp->dll,
274 (void **) &tmp->module);
275 if (error || !tmp->dll || !tmp->module) {
277 fprintf(stderr, "%s\n", error);*/
279 module_close(tmp->dll);
285 /* Append the new module to the end of the loaded modules */
286 mutex_lock(&loaded_modules_mutex);
287 for (tmp = loaded_modules ; tmp && tmp->next; tmp = tmp->next)
292 loaded_modules = *record;
293 mutex_unlock(&loaded_modules_mutex);
300 do_load_dir(const char *dirname, const char *prefix, const char *suffix,
301 int reqsym, verto_ev_type reqtypes, module_record **record)
304 struct dirent *ent = NULL;
307 dir = opendir(dirname);
312 while ((ent = readdir(dir))) {
317 flen = strlen(ent->d_name);
318 slen = strlen(suffix);
320 if (!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name))
322 if (strstr(ent->d_name, prefix) != ent->d_name)
324 if (flen < slen || strcmp(ent->d_name + flen - slen, suffix))
327 if (int_asprintf(&tmp, "%s/%s", dirname, ent->d_name) < 0)
330 success = do_load_file(tmp, reqsym, reqtypes, record);
338 return *record != NULL;
343 load_module(const char *impl, verto_ev_type reqtypes, module_record **record)
346 #ifndef BUILTIN_MODULE
352 /* Check the cache */
353 mutex_lock(&loaded_modules_mutex);
355 for (*record = loaded_modules ; *record ; *record = (*record)->next) {
356 if ((strchr(impl, '/') && !strcmp(impl, (*record)->filename))
357 || !strcmp(impl, (*record)->module->name)) {
358 mutex_unlock(&loaded_modules_mutex);
362 } else if (loaded_modules) {
363 for (*record = loaded_modules ; *record ; *record = (*record)->next) {
364 if (reqtypes == VERTO_EV_TYPE_NONE
365 || ((*record)->module->types & reqtypes) == reqtypes) {
366 mutex_unlock(&loaded_modules_mutex);
371 mutex_unlock(&loaded_modules_mutex);
373 #ifndef BUILTIN_MODULE
374 if (!module_get_filename_for_symbol(verto_convert_module, &prefix))
378 * prefix == /usr/lib/libverto-
381 * Put them all together: /usr/lib/libverto-glib.so.0 */
382 tmp = strdup(prefix);
388 suffix = basename(tmp);
389 suffix = strchr(suffix, '.');
390 if (!suffix || strlen(suffix) < 1 || !(suffix = strdup(suffix))) {
395 strcpy(prefix + strlen(prefix) - strlen(suffix), "-");
399 /* Try to do a load by the path */
400 if (!success && strchr(impl, '/'))
401 success = do_load_file(impl, 0, reqtypes, record);
403 /* Try to do a load by the name */
405 if (int_asprintf(&tmp, "%s%s%s", prefix, impl, suffix) > 0) {
406 success = do_load_file(tmp, 0, reqtypes, record);
411 /* NULL was passed, so we will use the dirname of
412 * the prefix to try and find any possible plugins */
413 tmp = strdup(prefix);
415 char *dname = strdup(dirname(tmp));
418 tmp = strdup(basename(prefix));
422 if (dname && prefix) {
423 /* Attempt to find a module we are already linked to */
424 success = do_load_dir(dname, prefix, suffix, 1, reqtypes,
427 #ifdef DEFAULT_MODULE
428 /* Attempt to find the default module */
429 success = load_module(DEFAULT_MODULE, reqtypes, record);
431 #endif /* DEFAULT_MODULE */
432 /* Attempt to load any plugin (we're desperate) */
433 success = do_load_dir(dname, prefix, suffix, 0,
444 #endif /* BUILTIN_MODULE */
449 make_ev(verto_ctx *ctx, verto_callback *callback,
450 verto_ev_type type, verto_ev_flag flags)
454 if (!ctx || !callback)
457 ev = vresize(NULL, sizeof(verto_ev));
459 memset(ev, 0, sizeof(verto_ev));
462 ev->callback = callback;
470 push_ev(verto_ctx *ctx, verto_ev *ev)
479 ctx->events->next = tmp;
483 remove_ev(verto_ev **origin, verto_ev *item)
485 if (!origin || !*origin || !item)
489 *origin = (*origin)->next;
491 remove_ev(&((*origin)->next), item);
495 signal_ignore(verto_ctx *ctx, verto_ev *ev)
500 verto_new(const char *impl, verto_ev_type reqtypes)
502 module_record *mr = NULL;
504 if (!load_module(impl, reqtypes, &mr))
507 return verto_convert_module(mr->module, 0, NULL);
511 verto_default(const char *impl, verto_ev_type reqtypes)
513 module_record *mr = NULL;
515 if (!load_module(impl, reqtypes, &mr))
518 return verto_convert_module(mr->module, 1, NULL);
522 verto_set_default(const char *impl, verto_ev_type reqtypes)
526 mutex_lock(&loaded_modules_mutex);
527 if (loaded_modules || !impl) {
528 mutex_unlock(&loaded_modules_mutex);
531 mutex_unlock(&loaded_modules_mutex);
533 return load_module(impl, reqtypes, &mr);
537 verto_set_allocator(void *(*resize)(void *mem, size_t size),
540 if (resize_cb || !resize)
543 resize_cb_hierarchical = hierarchical;
548 verto_free(verto_ctx *ctx)
553 ctx->ref = ctx->ref > 0 ? ctx->ref - 1 : 0;
557 /* Cancel all pending events */
559 verto_del(ctx->events);
561 /* Free the private */
562 if (!ctx->deflt || !ctx->module->funcs->ctx_default)
563 ctx->module->funcs->ctx_free(ctx->ctx);
569 verto_run(verto_ctx *ctx)
574 if (ctx->module->funcs->ctx_break && ctx->module->funcs->ctx_run)
575 ctx->module->funcs->ctx_run(ctx->ctx);
578 ctx->module->funcs->ctx_run_once(ctx->ctx);
584 verto_run_once(verto_ctx *ctx)
588 ctx->module->funcs->ctx_run_once(ctx->ctx);
592 verto_break(verto_ctx *ctx)
597 if (ctx->module->funcs->ctx_break && ctx->module->funcs->ctx_run)
598 ctx->module->funcs->ctx_break(ctx->ctx);
604 verto_reinitialize(verto_ctx *ctx)
606 verto_ev *tmp, *next;
612 /* Delete all events, but keep around the forkable ev structs */
613 for (tmp = ctx->events; tmp; tmp = next) {
616 if (tmp->flags & VERTO_EV_FLAG_REINITIABLE)
617 ctx->module->funcs->ctx_del(ctx->ctx, tmp, tmp->ev);
622 /* Reinit the loop */
623 if (ctx->module->funcs->ctx_reinitialize)
624 ctx->module->funcs->ctx_reinitialize(ctx->ctx);
626 /* Recreate events that were marked forkable */
627 for (tmp = ctx->events; tmp; tmp = tmp->next) {
628 tmp->actual = make_actual(tmp->flags);
629 tmp->ev = ctx->module->funcs->ctx_add(ctx->ctx, tmp, &tmp->actual);
637 #define doadd(ev, set, type) \
638 ev = make_ev(ctx, callback, type, flags); \
641 ev->actual = make_actual(ev->flags); \
642 ev->ev = ctx->module->funcs->ctx_add(ctx->ctx, ev, &ev->actual); \
651 verto_add_io(verto_ctx *ctx, verto_ev_flag flags,
652 verto_callback *callback, int fd)
656 if (fd < 0 || !(flags & (VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_IO_WRITE)))
659 doadd(ev, ev->option.io.fd = fd, VERTO_EV_TYPE_IO);
664 verto_add_timeout(verto_ctx *ctx, verto_ev_flag flags,
665 verto_callback *callback, time_t interval)
668 doadd(ev, ev->option.interval = interval, VERTO_EV_TYPE_TIMEOUT);
673 verto_add_idle(verto_ctx *ctx, verto_ev_flag flags,
674 verto_callback *callback)
677 doadd(ev,, VERTO_EV_TYPE_IDLE);
682 verto_add_signal(verto_ctx *ctx, verto_ev_flag flags,
683 verto_callback *callback, int signal)
690 if (signal == SIGCHLD)
693 if (callback == VERTO_SIG_IGN) {
694 callback = signal_ignore;
695 if (!(flags & VERTO_EV_FLAG_PERSIST))
698 doadd(ev, ev->option.signal = signal, VERTO_EV_TYPE_SIGNAL);
703 verto_add_child(verto_ctx *ctx, verto_ev_flag flags,
704 verto_callback *callback, verto_proc proc)
708 if (flags & VERTO_EV_FLAG_PERSIST) /* persist makes no sense */
716 doadd(ev, ev->option.child.proc = proc, VERTO_EV_TYPE_CHILD);
721 verto_set_private(verto_ev *ev, void *priv, verto_callback *free)
725 if (ev->onfree && free)
726 ev->onfree(ev->ctx, ev);
732 verto_get_private(const verto_ev *ev)
738 verto_get_type(const verto_ev *ev)
744 verto_get_flags(const verto_ev *ev)
750 verto_set_flags(verto_ev *ev, verto_ev_flag flags)
755 ev->flags &= ~_VERTO_EV_FLAG_MUTABLE_MASK;
756 ev->flags |= flags & _VERTO_EV_FLAG_MUTABLE_MASK;
758 /* If setting flags isn't supported, just rebuild the event */
759 if (!ev->ctx->module->funcs->ctx_set_flags) {
760 ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev);
761 ev->actual = make_actual(ev->flags);
762 ev->ev = ev->ctx->module->funcs->ctx_add(ev->ctx->ctx, ev, &ev->actual);
763 assert(ev->ev); /* Here is the main reason why modules should */
764 return; /* implement set_flags(): we cannot fail gracefully. */
767 ev->actual &= ~_VERTO_EV_FLAG_MUTABLE_MASK;
768 ev->actual |= flags & _VERTO_EV_FLAG_MUTABLE_MASK;
769 ev->ctx->module->funcs->ctx_set_flags(ev->ctx->ctx, ev, ev->ev);
773 verto_get_fd(const verto_ev *ev)
775 if (ev && (ev->type == VERTO_EV_TYPE_IO))
776 return ev->option.io.fd;
781 verto_get_fd_state(const verto_ev *ev)
783 return ev->option.io.state;
787 verto_get_interval(const verto_ev *ev)
789 if (ev && (ev->type == VERTO_EV_TYPE_TIMEOUT))
790 return ev->option.interval;
795 verto_get_signal(const verto_ev *ev)
797 if (ev && (ev->type == VERTO_EV_TYPE_SIGNAL))
798 return ev->option.signal;
803 verto_get_proc(const verto_ev *ev) {
804 if (ev && ev->type == VERTO_EV_TYPE_CHILD)
805 return ev->option.child.proc;
806 return (verto_proc) 0;
810 verto_get_proc_status(const verto_ev *ev)
812 return ev->option.child.status;
816 verto_get_ctx(const verto_ev *ev)
822 verto_del(verto_ev *ev)
827 /* If the event is freed in the callback, we just set a flag so that
828 * verto_fire() can actually do the delete when the callback completes.
830 * If we don't do this, than verto_fire() will access freed memory. */
837 ev->onfree(ev->ctx, ev);
838 ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev);
839 remove_ev(&(ev->ctx->events), ev);
841 if ((ev->type == VERTO_EV_TYPE_IO) &&
842 (ev->flags & VERTO_EV_FLAG_IO_CLOSE_FD) &&
843 !(ev->actual & VERTO_EV_FLAG_IO_CLOSE_FD))
844 close(ev->option.io.fd);
850 verto_get_supported_types(verto_ctx *ctx)
852 return ctx->module->types;
855 /*** THE FOLLOWING ARE FOR IMPLEMENTATION MODULES ONLY ***/
858 verto_convert_module(const verto_module *module, int deflt, verto_mod_ctx *mctx)
860 verto_ctx *ctx = NULL;
867 mutex_lock(&loaded_modules_mutex);
868 for (mr = loaded_modules ; mr ; mr = mr->next) {
870 if (mr->module == module && mr->defctx) {
872 module->funcs->ctx_free(mctx);
875 mutex_unlock(&loaded_modules_mutex);
879 mutex_unlock(&loaded_modules_mutex);
884 ? (module->funcs->ctx_default
885 ? module->funcs->ctx_default()
886 : module->funcs->ctx_new())
887 : module->funcs->ctx_new();
892 ctx = vresize(NULL, sizeof(verto_ctx));
895 memset(ctx, 0, sizeof(verto_ctx));
899 ctx->module = module;
905 mutex_lock(&loaded_modules_mutex);
906 tmp = &loaded_modules;
907 for (mr = loaded_modules ; mr ; mr = mr->next) {
908 if (mr->module == module) {
909 assert(mr->defctx == NULL);
911 mutex_unlock(&loaded_modules_mutex);
920 mutex_unlock(&loaded_modules_mutex);
922 *tmp = vresize(NULL, sizeof(module_record));
928 memset(*tmp, 0, sizeof(module_record));
929 (*tmp)->defctx = ctx;
930 (*tmp)->module = module;
937 module->funcs->ctx_free(mctx);
942 verto_fire(verto_ev *ev)
947 ev->callback(ev->ctx, ev);
950 if (ev->depth == 0) {
951 if (!(ev->flags & VERTO_EV_FLAG_PERSIST) || ev->deleted)
954 if (!(ev->actual & VERTO_EV_FLAG_PERSIST)) {
955 ev->actual = make_actual(ev->flags);
956 priv = ev->ctx->module->funcs->ctx_add(ev->ctx->ctx, ev, &ev->actual);
957 assert(priv); /* TODO: create an error callback */
958 ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev);
962 if (ev->type == VERTO_EV_TYPE_IO)
963 ev->option.io.state = VERTO_EV_FLAG_NONE;
964 if (ev->type == VERTO_EV_TYPE_CHILD)
965 ev->option.child.status = 0;
971 verto_set_proc_status(verto_ev *ev, verto_proc_status status)
973 if (ev && ev->type == VERTO_EV_TYPE_CHILD)
974 ev->option.child.status = status;
978 verto_set_fd_state(verto_ev *ev, verto_ev_flag state)
980 /* Filter out only the io flags */
981 state = state & (VERTO_EV_FLAG_IO_READ |
982 VERTO_EV_FLAG_IO_WRITE |
983 VERTO_EV_FLAG_IO_ERROR);
985 /* Don't report read/write if the socket is closed */
986 if (state & VERTO_EV_FLAG_IO_ERROR)
987 state = VERTO_EV_FLAG_IO_ERROR;
989 if (ev && ev->type == VERTO_EV_TYPE_IO)
990 ev->option.io.state = state;