1 /* 2 * Copyright 2011 Red Hat, Inc. 3 * 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: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 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 22 * SOFTWARE. 23 */ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <signal.h> 29 #include <assert.h> 30 #include <stdarg.h> 31 32 #include <libgen.h> 33 #include <sys/types.h> 34 #include <dirent.h> 35 36 #ifdef HAVE_PTHREAD 37 #include <pthread.h> 38 #endif 39 40 #include <verto-module.h> 41 #include "module.h" 42 43 #define _str(s) # s 44 #define __str(s) _str(s) 45 46 #define MUTABLE(flags) (flags & _VERTO_EV_FLAG_MUTABLE_MASK) 47 48 /* Remove flags we can emulate */ 49 #define make_actual(flags) ((flags) & ~(VERTO_EV_FLAG_PERSIST|VERTO_EV_FLAG_IO_CLOSE_FD)) 50 51 struct verto_ctx { 52 size_t ref; 53 verto_mod_ctx *ctx; 54 const verto_module *module; 55 verto_ev *events; 56 int deflt; 57 int exit; 58 }; 59 60 typedef struct { 61 verto_proc proc; 62 verto_proc_status status; 63 } verto_child; 64 65 typedef struct { 66 int fd; 67 verto_ev_flag state; 68 } verto_io; 69 70 struct verto_ev { 71 verto_ev *next; 72 verto_ctx *ctx; 73 verto_ev_type type; 74 verto_callback *callback; 75 verto_callback *onfree; 76 void *priv; 77 verto_mod_ev *ev; 78 verto_ev_flag flags; 79 verto_ev_flag actual; 80 size_t depth; 81 int deleted; 82 union { 83 verto_io io; 84 int signal; 85 time_t interval; 86 verto_child child; 87 } option; 88 }; 89 90 typedef struct module_record module_record; 91 struct module_record { 92 module_record *next; 93 const verto_module *module; 94 void *dll; 95 char *filename; 96 verto_ctx *defctx; 97 }; 98 99 100 #ifdef BUILTIN_MODULE 101 #define _MODTABLE(n) verto_module_table_ ## n 102 #define MODTABLE(n) _MODTABLE(n) 103 /* 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 <modulename>. 107 */ 108 extern verto_module MODTABLE(BUILTIN_MODULE); 109 static module_record builtin_record = { 110 NULL, &MODTABLE(BUILTIN_MODULE), NULL, "", NULL 111 }; 112 static module_record *loaded_modules = &builtin_record; 113 #else 114 static module_record *loaded_modules; 115 #endif 116 117 static void *(*resize_cb)(void *mem, size_t size); 118 static int resize_cb_hierarchical; 119 120 #ifdef HAVE_PTHREAD 121 static pthread_mutex_t loaded_modules_mutex = PTHREAD_MUTEX_INITIALIZER; 122 123 #ifndef NDEBUG 124 #define mutex_lock(x) { \ 125 int c = pthread_mutex_lock(x); \ 126 if (c != 0) { \ 127 fprintf(stderr, "pthread_mutex_lock returned %d (%s) in %s", \ 128 c, strerror(c), __FUNCTION__); \ 129 } \ 130 assert(c == 0); \ 131 } 132 #define mutex_unlock(x) { \ 133 int c = pthread_mutex_unlock(x); \ 134 if (c != 0) { \ 135 fprintf(stderr, "pthread_mutex_unlock returned %d (%s) in %s", \ 136 c, strerror(c), __FUNCTION__); \ 137 } \ 138 assert(c == 0); \ 139 } 140 #define mutex_destroy(x) { \ 141 int c = pthread_mutex_destroy(x); \ 142 if (c != 0) { \ 143 fprintf(stderr, "pthread_mutex_destroy returned %d (%s) in %s", \ 144 c, strerror(c), __FUNCTION__); \ 145 } \ 146 assert(c == 0); \ 147 } 148 #else /* NDEBUG */ 149 #define mutex_lock pthread_mutex_lock 150 #define mutex_unlock pthread_mutex_unlock 151 #define mutex_destroy pthread_mutex_destroy 152 #endif /* NDEBUG */ 153 154 #else /* HAVE_PTHREAD */ 155 #define mutex_lock(x) 156 #define mutex_unlock(x) 157 #define mutex_destroy(x) 158 #endif /* HAVE_PTHREAD */ 159 160 #define vfree(mem) vresize(mem, 0) 161 static void * 162 vresize(void *mem, size_t size) 163 { 164 if (!resize_cb) 165 resize_cb = &realloc; 166 if (size == 0 && resize_cb == &realloc) { 167 /* Avoid memleak as realloc(X, 0) can return a free-able pointer. */ 168 free(mem); 169 return NULL; 170 } 171 return (*resize_cb)(mem, size); 172 } 173 174 #ifndef BUILTIN_MODULE 175 static char * 176 string_aconcat(const char *first, const char *second, const char *third) { 177 char *ret; 178 size_t len; 179 180 len = strlen(first) + strlen(second); 181 if (third) 182 len += strlen(third); 183 184 ret = malloc(len + 1); 185 if (!ret) 186 return NULL; 187 188 strncpy(ret, first, strlen(first)); 189 strncpy(ret + strlen(first), second, strlen(second)); 190 if (third) 191 strncpy(ret + strlen(first) + strlen(second), third, strlen(third)); 192 193 ret[len] = '\0'; 194 return ret; 195 } 196 197 static char * 198 int_get_table_name_from_filename(const char *filename) 199 { 200 char *bn = NULL, *tmp = NULL; 201 202 if (!filename) 203 return NULL; 204 205 tmp = strdup(filename); 206 if (!tmp) 207 return NULL; 208 209 bn = basename(tmp); 210 if (bn) 211 bn = strdup(bn); 212 free(tmp); 213 if (!bn) 214 return NULL; 215 216 tmp = strchr(bn, '-'); 217 if (tmp) { 218 if (strchr(tmp+1, '.')) { 219 *strchr(tmp+1, '.') = '\0'; 220 tmp = string_aconcat(__str(VERTO_MODULE_TABLE()), tmp + 1, NULL); 221 } else 222 tmp = NULL; 223 } 224 225 free(bn); 226 return tmp; 227 } 228 229 typedef struct { 230 int reqsym; 231 verto_ev_type reqtypes; 232 } shouldload_data; 233 234 static int 235 shouldload(void *symb, void *misc, char **err) 236 { 237 verto_module *table = (verto_module*) symb; 238 shouldload_data *data = (shouldload_data*) misc; 239 240 /* Make sure we have the proper version */ 241 if (table->vers != VERTO_MODULE_VERSION) { 242 if (err) 243 *err = strdup("Invalid module version!"); 244 return 0; 245 } 246 247 /* Check to make sure that we have our required symbol if reqsym == true */ 248 if (table->symb && data->reqsym 249 && !module_symbol_is_present(NULL, table->symb)) { 250 if (err) 251 *err = string_aconcat("Symbol not found: ", table->symb, "!"); 252 return 0; 253 } 254 255 /* Check to make sure that this module supports our required features */ 256 if (data->reqtypes != VERTO_EV_TYPE_NONE 257 && (table->types & data->reqtypes) != data->reqtypes) { 258 if (err) 259 *err = strdup("Module does not support required features!"); 260 return 0; 261 } 262 263 return 1; 264 } 265 266 static int 267 do_load_file(const char *filename, int reqsym, verto_ev_type reqtypes, 268 module_record **record) 269 { 270 char *tblname = NULL, *error = NULL; 271 module_record *tmp; 272 shouldload_data data = { reqsym, reqtypes }; 273 274 /* Check the loaded modules to see if we already loaded one */ 275 mutex_lock(&loaded_modules_mutex); 276 for (*record = loaded_modules ; *record ; *record = (*record)->next) { 277 if (!strcmp((*record)->filename, filename)) { 278 mutex_unlock(&loaded_modules_mutex); 279 return 1; 280 } 281 } 282 mutex_unlock(&loaded_modules_mutex); 283 284 /* Create our module record */ 285 tmp = *record = vresize(NULL, sizeof(module_record)); 286 if (!tmp) 287 return 0; 288 memset(tmp, 0, sizeof(module_record)); 289 tmp->filename = strdup(filename); 290 if (!tmp->filename) { 291 vfree(tmp); 292 return 0; 293 } 294 295 /* Get the name of the module struct in the library */ 296 tblname = int_get_table_name_from_filename(filename); 297 if (!tblname) { 298 free(tblname); 299 free(tmp->filename); 300 vfree(tmp); 301 return 0; 302 } 303 304 /* Load the module */ 305 error = module_load(filename, tblname, shouldload, &data, &tmp->dll, 306 (void **) &tmp->module); 307 if (error || !tmp->dll || !tmp->module) { 308 /*if (error) 309 fprintf(stderr, "%s\n", error);*/ 310 free(error); 311 module_close(tmp->dll); 312 free(tblname); 313 free(tmp->filename); 314 vfree(tmp); 315 return 0; 316 } 317 318 /* Append the new module to the end of the loaded modules */ 319 mutex_lock(&loaded_modules_mutex); 320 for (tmp = loaded_modules ; tmp && tmp->next; tmp = tmp->next) 321 continue; 322 if (tmp) 323 tmp->next = *record; 324 else 325 loaded_modules = *record; 326 mutex_unlock(&loaded_modules_mutex); 327 328 free(tblname); 329 return 1; 330 } 331 332 static int 333 do_load_dir(const char *dirname, const char *prefix, const char *suffix, 334 int reqsym, verto_ev_type reqtypes, module_record **record) 335 { 336 DIR *dir; 337 struct dirent *ent = NULL; 338 339 *record = NULL; 340 dir = opendir(dirname); 341 if (!dir) 342 return 0; 343 344 345 while ((ent = readdir(dir))) { 346 char *tmp = NULL; 347 int success; 348 size_t flen, slen; 349 350 flen = strlen(ent->d_name); 351 slen = strlen(suffix); 352 353 if (!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name)) 354 continue; 355 if (strstr(ent->d_name, prefix) != ent->d_name) 356 continue; 357 if (flen < slen || strcmp(ent->d_name + flen - slen, suffix)) 358 continue; 359 360 tmp = string_aconcat(dirname, "/", ent->d_name); 361 if (!tmp) 362 continue; 363 364 success = do_load_file(tmp, reqsym, reqtypes, record); 365 free(tmp); 366 if (success) 367 break; 368 *record = NULL; 369 } 370 371 closedir(dir); 372 return *record != NULL; 373 } 374 #endif 375 376 static int 377 load_module(const char *impl, verto_ev_type reqtypes, module_record **record) 378 { 379 int success = 0; 380 #ifndef BUILTIN_MODULE 381 char *prefix = NULL; 382 char *suffix = NULL; 383 char *tmp = NULL; 384 #endif 385 386 /* Check the cache */ 387 mutex_lock(&loaded_modules_mutex); 388 if (impl) { 389 for (*record = loaded_modules ; *record ; *record = (*record)->next) { 390 if ((strchr(impl, '/') && !strcmp(impl, (*record)->filename)) 391 || !strcmp(impl, (*record)->module->name)) { 392 mutex_unlock(&loaded_modules_mutex); 393 return 1; 394 } 395 } 396 } else if (loaded_modules) { 397 for (*record = loaded_modules ; *record ; *record = (*record)->next) { 398 if (reqtypes == VERTO_EV_TYPE_NONE 399 || ((*record)->module->types & reqtypes) == reqtypes) { 400 mutex_unlock(&loaded_modules_mutex); 401 return 1; 402 } 403 } 404 } 405 mutex_unlock(&loaded_modules_mutex); 406 407 #ifndef BUILTIN_MODULE 408 if (!module_get_filename_for_symbol(verto_convert_module, &prefix)) 409 return 0; 410 411 /* Example output: 412 * prefix == /usr/lib/libverto- 413 * impl == glib 414 * suffix == .so.0 415 * Put them all together: /usr/lib/libverto-glib.so.0 */ 416 tmp = strdup(prefix); 417 if (!tmp) { 418 free(prefix); 419 return 0; 420 } 421 422 suffix = basename(tmp); 423 suffix = strchr(suffix, '.'); 424 if (!suffix || strlen(suffix) < 1 || !(suffix = strdup(suffix))) { 425 free(prefix); 426 free(tmp); 427 return 0; 428 } 429 strcpy(prefix + strlen(prefix) - strlen(suffix), "-"); 430 free(tmp); 431 432 if (impl) { 433 /* Try to do a load by the path */ 434 if (!success && strchr(impl, '/')) 435 success = do_load_file(impl, 0, reqtypes, record); 436 if (!success) { 437 /* Try to do a load by the name */ 438 tmp = string_aconcat(prefix, impl, suffix); 439 if (tmp) { 440 success = do_load_file(tmp, 0, reqtypes, record); 441 free(tmp); 442 } 443 } 444 } else { 445 /* NULL was passed, so we will use the dirname of 446 * the prefix to try and find any possible plugins */ 447 tmp = strdup(prefix); 448 if (tmp) { 449 char *dname = strdup(dirname(tmp)); 450 free(tmp); 451 452 tmp = strdup(basename(prefix)); 453 free(prefix); 454 prefix = tmp; 455 456 if (dname && prefix) { 457 /* Attempt to find a module we are already linked to */ 458 success = do_load_dir(dname, prefix, suffix, 1, reqtypes, 459 record); 460 if (!success) { 461 #ifdef DEFAULT_MODULE 462 /* Attempt to find the default module */ 463 success = load_module(DEFAULT_MODULE, reqtypes, record); 464 if (!success) 465 #endif /* DEFAULT_MODULE */ 466 /* Attempt to load any plugin (we're desperate) */ 467 success = do_load_dir(dname, prefix, suffix, 0, 468 reqtypes, record); 469 } 470 } 471 472 free(dname); 473 } 474 } 475 476 free(suffix); 477 free(prefix); 478 #endif /* BUILTIN_MODULE */ 479 return success; 480 } 481 482 static verto_ev * 483 make_ev(verto_ctx *ctx, verto_callback *callback, 484 verto_ev_type type, verto_ev_flag flags) 485 { 486 verto_ev *ev = NULL; 487 488 if (!ctx || !callback) 489 return NULL; 490 491 ev = vresize(NULL, sizeof(verto_ev)); 492 if (ev) { 493 memset(ev, 0, sizeof(verto_ev)); 494 ev->ctx = ctx; 495 ev->type = type; 496 ev->callback = callback; 497 ev->flags = flags; 498 } 499 500 return ev; 501 } 502 503 static void 504 push_ev(verto_ctx *ctx, verto_ev *ev) 505 { 506 verto_ev *tmp; 507 508 if (!ctx || !ev) 509 return; 510 511 tmp = ctx->events; 512 ctx->events = ev; 513 ctx->events->next = tmp; 514 } 515 516 static void 517 remove_ev(verto_ev **origin, verto_ev *item) 518 { 519 if (!origin || !*origin || !item) 520 return; 521 522 if (*origin == item) 523 *origin = (*origin)->next; 524 else 525 remove_ev(&((*origin)->next), item); 526 } 527 528 static void 529 signal_ignore(verto_ctx *ctx, verto_ev *ev) 530 { 531 (void) ctx; 532 (void) ev; 533 } 534 535 verto_ctx * 536 verto_new(const char *impl, verto_ev_type reqtypes) 537 { 538 module_record *mr = NULL; 539 540 if (!load_module(impl, reqtypes, &mr)) 541 return NULL; 542 543 return verto_convert_module(mr->module, 0, NULL); 544 } 545 546 verto_ctx * 547 verto_default(const char *impl, verto_ev_type reqtypes) 548 { 549 module_record *mr = NULL; 550 551 if (!load_module(impl, reqtypes, &mr)) 552 return NULL; 553 554 return verto_convert_module(mr->module, 1, NULL); 555 } 556 557 int 558 verto_set_default(const char *impl, verto_ev_type reqtypes) 559 { 560 module_record *mr; 561 562 mutex_lock(&loaded_modules_mutex); 563 if (loaded_modules || !impl) { 564 mutex_unlock(&loaded_modules_mutex); 565 return 0; 566 } 567 mutex_unlock(&loaded_modules_mutex); 568 569 return load_module(impl, reqtypes, &mr); 570 } 571 572 int 573 verto_set_allocator(void *(*resize)(void *mem, size_t size), 574 int hierarchical) 575 { 576 if (resize_cb || !resize) 577 return 0; 578 resize_cb = resize; 579 resize_cb_hierarchical = hierarchical; 580 return 1; 581 } 582 583 void 584 verto_free(verto_ctx *ctx) 585 { 586 if (!ctx) 587 return; 588 589 ctx->ref = ctx->ref > 0 ? ctx->ref - 1 : 0; 590 if (ctx->ref > 0) 591 return; 592 593 /* Cancel all pending events */ 594 while (ctx->events) 595 verto_del(ctx->events); 596 597 /* Free the private */ 598 if (!ctx->deflt || !ctx->module->funcs->ctx_default) 599 ctx->module->funcs->ctx_free(ctx->ctx); 600 601 vfree(ctx); 602 } 603 604 void 605 verto_cleanup(void) 606 { 607 module_record *record; 608 609 mutex_lock(&loaded_modules_mutex); 610 611 for (record = loaded_modules; record; record = record->next) { 612 module_close(record->dll); 613 free(record->filename); 614 } 615 616 vfree(loaded_modules); 617 loaded_modules = NULL; 618 619 mutex_unlock(&loaded_modules_mutex); 620 mutex_destroy(&loaded_modules_mutex); 621 } 622 623 void 624 verto_run(verto_ctx *ctx) 625 { 626 if (!ctx) 627 return; 628 629 if (ctx->module->funcs->ctx_break && ctx->module->funcs->ctx_run) 630 ctx->module->funcs->ctx_run(ctx->ctx); 631 else { 632 while (!ctx->exit) 633 ctx->module->funcs->ctx_run_once(ctx->ctx); 634 ctx->exit = 0; 635 } 636 } 637 638 void 639 verto_run_once(verto_ctx *ctx) 640 { 641 if (!ctx) 642 return; 643 ctx->module->funcs->ctx_run_once(ctx->ctx); 644 } 645 646 void 647 verto_break(verto_ctx *ctx) 648 { 649 if (!ctx) 650 return; 651 652 if (ctx->module->funcs->ctx_break && ctx->module->funcs->ctx_run) 653 ctx->module->funcs->ctx_break(ctx->ctx); 654 else 655 ctx->exit = 1; 656 } 657 658 int 659 verto_reinitialize(verto_ctx *ctx) 660 { 661 verto_ev *tmp, *next; 662 int error = 1; 663 664 if (!ctx) 665 return 0; 666 667 /* Delete all events, but keep around the forkable ev structs */ 668 for (tmp = ctx->events; tmp; tmp = next) { 669 next = tmp->next; 670 671 if (tmp->flags & VERTO_EV_FLAG_REINITIABLE) 672 ctx->module->funcs->ctx_del(ctx->ctx, tmp, tmp->ev); 673 else 674 verto_del(tmp); 675 } 676 677 /* Reinit the loop */ 678 if (ctx->module->funcs->ctx_reinitialize) 679 ctx->module->funcs->ctx_reinitialize(ctx->ctx); 680 681 /* Recreate events that were marked forkable */ 682 for (tmp = ctx->events; tmp; tmp = tmp->next) { 683 tmp->actual = make_actual(tmp->flags); 684 tmp->ev = ctx->module->funcs->ctx_add(ctx->ctx, tmp, &tmp->actual); 685 if (!tmp->ev) 686 error = 0; 687 } 688 689 return error; 690 } 691 692 #define doadd(ev, set, type) \ 693 ev = make_ev(ctx, callback, type, flags); \ 694 if (ev) { \ 695 set; \ 696 ev->actual = make_actual(ev->flags); \ 697 ev->ev = ctx->module->funcs->ctx_add(ctx->ctx, ev, &ev->actual); \ 698 if (!ev->ev) { \ 699 vfree(ev); \ 700 return NULL; \ 701 } \ 702 push_ev(ctx, ev); \ 703 } 704 705 verto_ev * 706 verto_add_io(verto_ctx *ctx, verto_ev_flag flags, 707 verto_callback *callback, int fd) 708 { 709 verto_ev *ev; 710 711 if (fd < 0 || !(flags & (VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_IO_WRITE))) 712 return NULL; 713 714 doadd(ev, ev->option.io.fd = fd, VERTO_EV_TYPE_IO); 715 return ev; 716 } 717 718 verto_ev * 719 verto_add_timeout(verto_ctx *ctx, verto_ev_flag flags, 720 verto_callback *callback, time_t interval) 721 { 722 verto_ev *ev; 723 doadd(ev, ev->option.interval = interval, VERTO_EV_TYPE_TIMEOUT); 724 return ev; 725 } 726 727 verto_ev * 728 verto_add_idle(verto_ctx *ctx, verto_ev_flag flags, 729 verto_callback *callback) 730 { 731 verto_ev *ev; 732 doadd(ev,, VERTO_EV_TYPE_IDLE); 733 return ev; 734 } 735 736 verto_ev * 737 verto_add_signal(verto_ctx *ctx, verto_ev_flag flags, 738 verto_callback *callback, int signal) 739 { 740 verto_ev *ev; 741 742 if (signal < 0) 743 return NULL; 744 #ifndef WIN32 745 if (signal == SIGCHLD) 746 return NULL; 747 #endif 748 if (callback == VERTO_SIG_IGN) { 749 callback = signal_ignore; 750 if (!(flags & VERTO_EV_FLAG_PERSIST)) 751 return NULL; 752 } 753 doadd(ev, ev->option.signal = signal, VERTO_EV_TYPE_SIGNAL); 754 return ev; 755 } 756 757 verto_ev * 758 verto_add_child(verto_ctx *ctx, verto_ev_flag flags, 759 verto_callback *callback, verto_proc proc) 760 { 761 verto_ev *ev; 762 763 if (flags & VERTO_EV_FLAG_PERSIST) /* persist makes no sense */ 764 return NULL; 765 #ifdef WIN32 766 if (proc == NULL) 767 #else 768 if (proc < 1) 769 #endif 770 return NULL; 771 doadd(ev, ev->option.child.proc = proc, VERTO_EV_TYPE_CHILD); 772 return ev; 773 } 774 775 void 776 verto_set_private(verto_ev *ev, void *priv, verto_callback *free) 777 { 778 if (!ev) 779 return; 780 if (ev->onfree && free) 781 ev->onfree(ev->ctx, ev); 782 ev->priv = priv; 783 ev->onfree = free; 784 } 785 786 void * 787 verto_get_private(const verto_ev *ev) 788 { 789 return ev->priv; 790 } 791 792 verto_ev_type 793 verto_get_type(const verto_ev *ev) 794 { 795 return ev->type; 796 } 797 798 verto_ev_flag 799 verto_get_flags(const verto_ev *ev) 800 { 801 return ev->flags; 802 } 803 804 void 805 verto_set_flags(verto_ev *ev, verto_ev_flag flags) 806 { 807 if (!ev) 808 return; 809 810 /* No modification is needed, so do nothing. */ 811 if (MUTABLE(ev->flags) == MUTABLE(flags)) 812 return; 813 814 ev->flags &= ~_VERTO_EV_FLAG_MUTABLE_MASK; 815 ev->flags |= MUTABLE(flags); 816 817 /* If setting flags isn't supported, just rebuild the event */ 818 if (!ev->ctx->module->funcs->ctx_set_flags) { 819 ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev); 820 ev->actual = make_actual(ev->flags); 821 ev->ev = ev->ctx->module->funcs->ctx_add(ev->ctx->ctx, ev, &ev->actual); 822 assert(ev->ev); /* Here is the main reason why modules should */ 823 return; /* implement set_flags(): we cannot fail gracefully. */ 824 } 825 826 ev->actual &= ~_VERTO_EV_FLAG_MUTABLE_MASK; 827 ev->actual |= MUTABLE(flags); 828 ev->ctx->module->funcs->ctx_set_flags(ev->ctx->ctx, ev, ev->ev); 829 } 830 831 int 832 verto_get_fd(const verto_ev *ev) 833 { 834 if (ev && (ev->type == VERTO_EV_TYPE_IO)) 835 return ev->option.io.fd; 836 return -1; 837 } 838 839 verto_ev_flag 840 verto_get_fd_state(const verto_ev *ev) 841 { 842 return ev->option.io.state; 843 } 844 845 time_t 846 verto_get_interval(const verto_ev *ev) 847 { 848 if (ev && (ev->type == VERTO_EV_TYPE_TIMEOUT)) 849 return ev->option.interval; 850 return 0; 851 } 852 853 int 854 verto_get_signal(const verto_ev *ev) 855 { 856 if (ev && (ev->type == VERTO_EV_TYPE_SIGNAL)) 857 return ev->option.signal; 858 return -1; 859 } 860 861 verto_proc 862 verto_get_proc(const verto_ev *ev) { 863 if (ev && ev->type == VERTO_EV_TYPE_CHILD) 864 return ev->option.child.proc; 865 return (verto_proc) 0; 866 } 867 868 verto_proc_status 869 verto_get_proc_status(const verto_ev *ev) 870 { 871 return ev->option.child.status; 872 } 873 874 verto_ctx * 875 verto_get_ctx(const verto_ev *ev) 876 { 877 return ev->ctx; 878 } 879 880 void 881 verto_del(verto_ev *ev) 882 { 883 if (!ev) 884 return; 885 886 /* If the event is freed in the callback, we just set a flag so that 887 * verto_fire() can actually do the delete when the callback completes. 888 * 889 * If we don't do this, than verto_fire() will access freed memory. */ 890 if (ev->depth > 0) { 891 ev->deleted = 1; 892 return; 893 } 894 895 if (ev->onfree) 896 ev->onfree(ev->ctx, ev); 897 ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev); 898 remove_ev(&(ev->ctx->events), ev); 899 900 if ((ev->type == VERTO_EV_TYPE_IO) && 901 (ev->flags & VERTO_EV_FLAG_IO_CLOSE_FD) && 902 !(ev->actual & VERTO_EV_FLAG_IO_CLOSE_FD)) 903 close(ev->option.io.fd); 904 905 vfree(ev); 906 } 907 908 verto_ev_type 909 verto_get_supported_types(verto_ctx *ctx) 910 { 911 return ctx->module->types; 912 } 913 914 /*** THE FOLLOWING ARE FOR IMPLEMENTATION MODULES ONLY ***/ 915 916 verto_ctx * 917 verto_convert_module(const verto_module *module, int deflt, verto_mod_ctx *mctx) 918 { 919 verto_ctx *ctx = NULL; 920 module_record *mr; 921 922 if (!module) 923 return NULL; 924 925 if (deflt) { 926 mutex_lock(&loaded_modules_mutex); 927 for (mr = loaded_modules ; mr ; mr = mr->next) { 928 verto_ctx *tmp; 929 if (mr->module == module && mr->defctx) { 930 if (mctx) 931 module->funcs->ctx_free(mctx); 932 tmp = mr->defctx; 933 tmp->ref++; 934 mutex_unlock(&loaded_modules_mutex); 935 return tmp; 936 } 937 } 938 mutex_unlock(&loaded_modules_mutex); 939 } 940 941 if (!mctx) { 942 mctx = deflt 943 ? (module->funcs->ctx_default 944 ? module->funcs->ctx_default() 945 : module->funcs->ctx_new()) 946 : module->funcs->ctx_new(); 947 if (!mctx) 948 goto error; 949 } 950 951 ctx = vresize(NULL, sizeof(verto_ctx)); 952 if (!ctx) 953 goto error; 954 memset(ctx, 0, sizeof(verto_ctx)); 955 956 ctx->ref = 1; 957 ctx->ctx = mctx; 958 ctx->module = module; 959 ctx->deflt = deflt; 960 961 if (deflt) { 962 module_record **tmp; 963 964 mutex_lock(&loaded_modules_mutex); 965 tmp = &loaded_modules; 966 for (mr = loaded_modules ; mr ; mr = mr->next) { 967 if (mr->module == module) { 968 assert(mr->defctx == NULL); 969 mr->defctx = ctx; 970 mutex_unlock(&loaded_modules_mutex); 971 return ctx; 972 } 973 974 if (!mr->next) { 975 tmp = &mr->next; 976 break; 977 } 978 } 979 mutex_unlock(&loaded_modules_mutex); 980 981 *tmp = vresize(NULL, sizeof(module_record)); 982 if (!*tmp) { 983 vfree(ctx); 984 goto error; 985 } 986 987 memset(*tmp, 0, sizeof(module_record)); 988 (*tmp)->defctx = ctx; 989 (*tmp)->module = module; 990 } 991 992 return ctx; 993 994 error: 995 if (mctx) 996 module->funcs->ctx_free(mctx); 997 return NULL; 998 } 999 1000 void 1001 verto_fire(verto_ev *ev) 1002 { 1003 void *priv; 1004 1005 ev->depth++; 1006 ev->callback(ev->ctx, ev); 1007 ev->depth--; 1008 1009 if (ev->depth == 0) { 1010 if (!(ev->flags & VERTO_EV_FLAG_PERSIST) || ev->deleted) 1011 verto_del(ev); 1012 else { 1013 if (!(ev->actual & VERTO_EV_FLAG_PERSIST)) { 1014 ev->actual = make_actual(ev->flags); 1015 priv = ev->ctx->module->funcs->ctx_add(ev->ctx->ctx, ev, &ev->actual); 1016 assert(priv); /* TODO: create an error callback */ 1017 ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev); 1018 ev->ev = priv; 1019 } 1020 1021 if (ev->type == VERTO_EV_TYPE_IO) 1022 ev->option.io.state = VERTO_EV_FLAG_NONE; 1023 if (ev->type == VERTO_EV_TYPE_CHILD) 1024 ev->option.child.status = 0; 1025 } 1026 } 1027 } 1028 1029 void 1030 verto_set_proc_status(verto_ev *ev, verto_proc_status status) 1031 { 1032 if (ev && ev->type == VERTO_EV_TYPE_CHILD) 1033 ev->option.child.status = status; 1034 } 1035 1036 void 1037 verto_set_fd_state(verto_ev *ev, verto_ev_flag state) 1038 { 1039 /* Filter out only the io flags */ 1040 state = state & (VERTO_EV_FLAG_IO_READ | 1041 VERTO_EV_FLAG_IO_WRITE | 1042 VERTO_EV_FLAG_IO_ERROR); 1043 1044 /* Don't report read/write if the socket is closed */ 1045 if (state & VERTO_EV_FLAG_IO_ERROR) 1046 state = VERTO_EV_FLAG_IO_ERROR; 1047 1048 if (ev && ev->type == VERTO_EV_TYPE_IO) 1049 ev->option.io.state = state; 1050 } 1051