aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2020-02-17 22:41:13 -0800
committerJustin M. Keyes <justinkz@gmail.com>2020-02-17 22:41:13 -0800
commit6d48d0bd1598182c874f1ad5d72b4671944308bb (patch)
tree6b476388b9b5ab51afdebfa4362cd810f1f5cee6
parenta2efc9cf8b0fdf14b01156ba424145e1847f789c (diff)
downloadrneovim-6d48d0bd1598182c874f1ad5d72b4671944308bb.tar.gz
rneovim-6d48d0bd1598182c874f1ad5d72b4671944308bb.tar.bz2
rneovim-6d48d0bd1598182c874f1ad5d72b4671944308bb.zip
loop_close: call uv_stop(), fix bug
- Call uv_stop(). - Restore `uv_loop_close` condition (braindead cosmetic change from a2efc9cf8b0f that caused uv_loop_close *not* to be called if wait=false, sorry). Not doing `uv_walk(() => uv_close)`: see source comment for explanation. fix #11820 fix #7376 Q: Should we restore use of `UV_RUN_DEFAULT`/`UV_RUN_ONCE` (removed in a2efc9cf8b0f)? A: The while-loop (hopefully) achieves the same purpose while avoiding a hang.
-rw-r--r--src/nvim/event/loop.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c
index 664f3ad89d..902b7edc54 100644
--- a/src/nvim/event/loop.c
+++ b/src/nvim/event/loop.c
@@ -116,10 +116,20 @@ void loop_on_put(MultiQueue *queue, void *data)
uv_stop(&loop->uv);
}
+/// Closes `loop` and its handles, and frees its structures.
+///
+/// @param loop Loop to destroy
+/// @param wait Wait briefly for handles to deref
+///
/// @returns false if the loop could not be closed gracefully
bool loop_close(Loop *loop, bool wait)
{
bool rv = true;
+ // Loop won’t block for I/O after this.
+ uv_stop(&loop->uv);
+ // TODO(justinmk): Close all (lua/luv!) handles. But walk_cb() needs to call
+ // the resource-specific close-callbacks...
+ // uv_walk((h) => { if !uv_is_closing(h) { uv_close(h, …) } })
uv_mutex_destroy(&loop->mutex);
uv_close((uv_handle_t *)&loop->children_watcher, NULL);
uv_close((uv_handle_t *)&loop->children_kill_timer, NULL);
@@ -127,11 +137,14 @@ bool loop_close(Loop *loop, bool wait)
uv_close((uv_handle_t *)&loop->async, NULL);
uint64_t start = wait ? os_hrtime() : 0;
while (true) {
+ // Run the loop to tickle close-callbacks (which should then free memory).
+ // Use UV_RUN_NOWAIT to avoid a hang. #11820
uv_run(&loop->uv, UV_RUN_NOWAIT);
- if (!wait || (uv_loop_close(&loop->uv) != UV_EBUSY)) {
+ if ((uv_loop_close(&loop->uv) != UV_EBUSY) || !wait) {
break;
}
- if (os_hrtime() - start >= 2 * 1000000000) {
+ uint64_t elapsed_s = (os_hrtime() - start) / 1000000000; // seconds
+ if (elapsed_s >= 2) {
// Some libuv resource was not correctly deref'd. Log and bail.
rv = false;
ELOG("uv_loop_close() hang?");