diff options
| author | Justin M. Keyes <justinkz@gmail.com> | 2017-05-30 01:25:25 +0200 |
|---|---|---|
| committer | Justin M. Keyes <justinkz@gmail.com> | 2017-06-07 00:26:21 +0200 |
| commit | 698ec9eb6e97ce9038e5f95a3208b7a0ac8da805 (patch) | |
| tree | 0692e508d6a455adaa59b611fee8802b0033df7e /src/nvim/event | |
| parent | f83d733318d27ed8ad9fc7a442142ee8a74b7a39 (diff) | |
| download | rneovim-698ec9eb6e97ce9038e5f95a3208b7a0ac8da805.tar.gz rneovim-698ec9eb6e97ce9038e5f95a3208b7a0ac8da805.tar.bz2 rneovim-698ec9eb6e97ce9038e5f95a3208b7a0ac8da805.zip | |
loop_close: Avoid infinite loop, and log it.
Avoids a hang, and also helps diagnose issues like:
https://github.com/neovim/neovim/pull/6594#issuecomment-298321826
Diffstat (limited to 'src/nvim/event')
| -rw-r--r-- | src/nvim/event/loop.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c index c709ce9a1c..25701a1621 100644 --- a/src/nvim/event/loop.c +++ b/src/nvim/event/loop.c @@ -8,6 +8,7 @@ #include "nvim/event/loop.h" #include "nvim/event/process.h" +#include "nvim/log.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "event/loop.c.generated.h" @@ -78,20 +79,34 @@ void loop_on_put(MultiQueue *queue, void *data) uv_stop(&loop->uv); } -void loop_close(Loop *loop, bool wait) +/// @returns false if the loop could not be closed gracefully +bool loop_close(Loop *loop, bool wait) { + bool rv = true; uv_mutex_destroy(&loop->mutex); uv_close((uv_handle_t *)&loop->children_watcher, NULL); uv_close((uv_handle_t *)&loop->children_kill_timer, NULL); uv_close((uv_handle_t *)&loop->poll_timer, NULL); uv_close((uv_handle_t *)&loop->async, NULL); - do { + uint64_t start = wait ? os_hrtime() : 0; + while (true) { uv_run(&loop->uv, wait ? UV_RUN_DEFAULT : UV_RUN_NOWAIT); - } while (uv_loop_close(&loop->uv) && wait); + if (!uv_loop_close(&loop->uv) || !wait) { + break; + } + if (os_hrtime() - start >= 2 * 1000000000) { + // Some libuv resource was not correctly deref'd. Log and bail. + rv = false; + ELOG("uv_loop_close() hang?"); + log_uv_handles(&loop->uv); + break; + } + } multiqueue_free(loop->fast_events); multiqueue_free(loop->thread_events); multiqueue_free(loop->events); kl_destroy(WatcherPtr, loop->children); + return rv; } void loop_purge(Loop *loop) |