| 2581 | } |
| 2582 | |
| 2583 | void shutdown_plugins(struct lightningd *ld) |
| 2584 | { |
| 2585 | struct plugin *p, *next; |
| 2586 | |
| 2587 | /* Tell them all to shutdown; if they care. */ |
| 2588 | list_for_each_safe(&ld->plugins->plugins, p, next, list) { |
| 2589 | /* Clear all pending requests, so we don't try to answer them. */ |
| 2590 | strmap_iterate(&p->pending_requests, release_request, p); |
| 2591 | strmap_clear(&p->pending_requests); |
| 2592 | /* Kill immediately, deletes self from list. */ |
| 2593 | if (p->plugin_state != INIT_COMPLETE || !notify_plugin_shutdown(ld, p)) |
| 2594 | tal_free(p); |
| 2595 | } |
| 2596 | |
| 2597 | /* If anyone was interested in shutdown, give them time. */ |
| 2598 | if (!list_empty(&ld->plugins->plugins)) { |
| 2599 | struct timers *timer; |
| 2600 | struct timer *expired; |
| 2601 | |
| 2602 | /* 30 seconds should do it, use a clean timers struct */ |
| 2603 | timer = tal(NULL, struct timers); |
| 2604 | timers_init(timer, time_mono()); |
| 2605 | new_reltimer(timer, timer, time_from_sec(30), NULL, NULL); |
| 2606 | |
| 2607 | void *ret = io_loop(timer, &expired); |
| 2608 | assert(ret == NULL || ret == destroy_plugin); |
| 2609 | |
| 2610 | /* Report and free remaining plugins. */ |
| 2611 | while (!list_empty(&ld->plugins->plugins)) { |
| 2612 | p = list_pop(&ld->plugins->plugins, struct plugin, list); |
| 2613 | log_debug(ld->log, |
| 2614 | "%s: failed to self-terminate in time, killing.", |
| 2615 | p->shortname); |
| 2616 | tal_free(p); |
| 2617 | } |
| 2618 | } |
| 2619 | } |
| 2620 | |
| 2621 | static void dev_save_plugin_io(struct plugins *plugins, |
| 2622 | const char *type, |
no test coverage detected