diff --git a/lib/libuv.c b/lib/libuv.c index a230b57f..3e22c501 100644 --- a/lib/libuv.c +++ b/lib/libuv.c @@ -106,7 +106,7 @@ lws_io_cb(uv_poll_t *watcher, int status, int revents) LWS_VISIBLE void lws_uv_sigint_cb(uv_signal_t *watcher, int signum) { - lwsl_info("internal signal handler caught signal %d\n", signum); + lwsl_err("internal signal handler caught signal %d\n", signum); lws_libuv_stop(watcher->data); } @@ -156,8 +156,10 @@ lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, int tsi) return 1; #endif pt->ev_loop_foreign = 0; - } else + } else { + lwsl_notice(" Using foreign event loop...\n"); pt->ev_loop_foreign = 1; + } pt->io_loop_uv = loop; uv_idle_init(loop, &pt->uv_idle); @@ -183,16 +185,15 @@ lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, int tsi) if (vh->lserv_wsi) { vh->lserv_wsi->w_read.context = context; n = uv_poll_init_socket(pt->io_loop_uv, - &vh->lserv_wsi->w_read.uv_watcher, - vh->lserv_wsi->sock); + &vh->lserv_wsi->w_read.uv_watcher, + vh->lserv_wsi->sock); if (n) { lwsl_err("uv_poll_init failed %d, sockfd=%p\n", n, (void *)(long)vh->lserv_wsi->sock); return -1; } - uv_poll_start(&vh->lserv_wsi->w_read.uv_watcher, - UV_READABLE, lws_io_cb); + lws_libuv_io(vh->lserv_wsi, LWS_EV_START | LWS_EV_READ); } vh = vh->vhost_next; } @@ -203,12 +204,12 @@ lws_uv_initloop(struct lws_context *context, uv_loop_t *loop, int tsi) return status; } -void lws_uv_close_cb(uv_handle_t *handle) +static void lws_uv_close_cb(uv_handle_t *handle) { - + //lwsl_err("%s\n", __func__); } -void lws_uv_walk_cb(uv_handle_t *handle, void *arg) +static void lws_uv_walk_cb(uv_handle_t *handle, void *arg) { uv_close(handle, lws_uv_close_cb); } @@ -217,7 +218,7 @@ void lws_libuv_destroyloop(struct lws_context *context, int tsi) { struct lws_context_per_thread *pt = &context->pt[tsi]; - int m; + int m, budget = 100; if (!lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV)) return; @@ -227,19 +228,39 @@ lws_libuv_destroyloop(struct lws_context *context, int tsi) if (context->use_ev_sigint) uv_signal_stop(&pt->w_sigint.uv_watcher); - for (m = 0; m < ARRAY_SIZE(sigs); m++) + + for (m = 0; m < ARRAY_SIZE(sigs); m++) { uv_signal_stop(&pt->signals[m]); - if (!pt->ev_loop_foreign) { - uv_stop(pt->io_loop_uv); - uv_walk(pt->io_loop_uv, lws_uv_walk_cb, NULL); - while (uv_run(pt->io_loop_uv, UV_RUN_NOWAIT)); -#if UV_VERSION_MAJOR > 0 - m = uv_loop_close(pt->io_loop_uv); - if (m == UV_EBUSY) - lwsl_debug("%s: uv_loop_close: UV_EBUSY\n", __func__); -#endif - lws_free(pt->io_loop_uv); + uv_close((uv_handle_t *)&pt->signals[m], lws_uv_close_cb); } + + uv_timer_stop(&pt->uv_timeout_watcher); + uv_close((uv_handle_t *)&pt->uv_timeout_watcher, lws_uv_close_cb); + + uv_idle_stop(&pt->uv_idle); + uv_close((uv_handle_t *)&pt->uv_idle, lws_uv_close_cb); + + while (budget-- && uv_run(pt->io_loop_uv, UV_RUN_NOWAIT)) + ; + + if (!pt->ev_loop_foreign) + uv_stop(pt->io_loop_uv); + + if (pt->ev_loop_foreign) + return; + + uv_walk(pt->io_loop_uv, lws_uv_walk_cb, NULL); + if (pt->ev_loop_foreign) + return; + + while (uv_run(pt->io_loop_uv, UV_RUN_NOWAIT)) + ; +#if UV_VERSION_MAJOR > 0 + m = uv_loop_close(pt->io_loop_uv); + if (m == UV_EBUSY) + lwsl_err("%s: uv_loop_close: UV_EBUSY\n", __func__); +#endif + lws_free(pt->io_loop_uv); } void @@ -335,9 +356,10 @@ lws_libuv_kill(const struct lws_context *context) int n; for (n = 0; n < context->count_threads; n++) - if (context->pt[n].io_loop_uv && LWS_LIBUV_ENABLED(context)) + if (context->pt[n].io_loop_uv && + LWS_LIBUV_ENABLED(context) && + !context->pt[n].ev_loop_foreign) uv_stop(context->pt[n].io_loop_uv); - // TODO uv_stop check foreign loop? or not? } /* diff --git a/lib/lws-plat-unix.c b/lib/lws-plat-unix.c index 98b6c588..e26b041f 100644 --- a/lib/lws-plat-unix.c +++ b/lib/lws-plat-unix.c @@ -567,6 +567,10 @@ lws_plat_delete_socket_from_fds(struct lws_context *context, struct lws *wsi, int m) { struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi]; + + lws_libev_io(wsi, LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE); + lws_libuv_io(wsi, LWS_EV_STOP | LWS_EV_READ | LWS_EV_WRITE); + pt->fds_count--; } diff --git a/test-server/test-server-libuv.c b/test-server/test-server-libuv.c index f3cdffa8..986a3d85 100644 --- a/test-server/test-server-libuv.c +++ b/test-server/test-server-libuv.c @@ -20,6 +20,7 @@ */ #include "test-server.h" +#include int close_testing; int max_poll_elements; @@ -165,6 +166,7 @@ static struct option options[] = { { NULL, 0, 0, 0 } }; +#if UV_VERSION_MAJOR > 0 /* ----- this code is only needed for foreign / external libuv tests -----*/ struct counter { @@ -211,11 +213,13 @@ static void lws_uv_walk_cb(uv_handle_t *handle, void *arg) } /* --- end of foreign test code ---- */ +#endif int main(int argc, char **argv) { struct lws_context_creation_info info; char interface_name[128] = ""; +#if UV_VERSION_MAJOR > 0 /* --- only needed for foreign loop test ---> */ uv_loop_t loop; uv_signal_t signal_outer; @@ -223,6 +227,7 @@ int main(int argc, char **argv) struct counter ctr; int foreign_libuv_loop = 0; /* <--- only needed for foreign loop test --- */ +#endif uv_timer_t timeout_watcher; const char *iface = NULL; char cert_path[1024]; @@ -250,7 +255,9 @@ int main(int argc, char **argv) continue; switch (n) { case 'f': +#if UV_VERSION_MAJOR > 0 foreign_libuv_loop = 1; +#endif break; case 'e': opts |= LWS_SERVER_OPTION_LIBEV; @@ -356,6 +363,7 @@ int main(int argc, char **argv) info.timeout_secs = 5; info.options = opts | LWS_SERVER_OPTION_LIBUV; +#if UV_VERSION_MAJOR > 0 if (foreign_libuv_loop) { /* create the foreign loop */ uv_loop_init(&loop); @@ -377,6 +385,7 @@ int main(int argc, char **argv) /* timer will stop loop and we will get here */ } +#endif context = lws_create_context(&info); if (context == NULL) { @@ -386,10 +395,13 @@ int main(int argc, char **argv) lws_uv_sigint_cfg(context, 1, signal_cb); +#if UV_VERSION_MAJOR > 0 if (foreign_libuv_loop) /* we have our own uv loop outside of lws */ lws_uv_initloop(context, &loop, 0); - else { + else +#endif + { /* * lws will create his own libuv loop in the context */ @@ -403,7 +415,7 @@ int main(int argc, char **argv) uv_timer_init(lws_uv_getloop(context, 0), &timeout_watcher); uv_timer_start(&timeout_watcher, uv_timeout_cb_dumb_increment, 50, 50); - +#if UV_VERSION_MAJOR > 0 if (foreign_libuv_loop) { /* * prepare inner timer on loop, to run along with lws. @@ -474,7 +486,9 @@ int main(int argc, char **argv) lwsl_notice("uv loop close rc %s\n", e ? uv_strerror(e) : "ok"); - } else { + } else +#endif + { lws_libuv_run(context, 0); bail: