mirror of
https://github.com/neovim/neovim.git
synced 2025-11-26 12:10:40 +00:00
Merge #11887 'loop_close: close all handles'
This commit is contained in:
@@ -116,6 +116,20 @@ void loop_on_put(MultiQueue *queue, void *data)
|
||||
uv_stop(&loop->uv);
|
||||
}
|
||||
|
||||
#if !defined(EXITFREE)
|
||||
static void loop_walk_cb(uv_handle_t *handle, void *arg)
|
||||
{
|
||||
if (!uv_is_closing(handle)) {
|
||||
uv_close(handle, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// 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)
|
||||
{
|
||||
@@ -126,18 +140,34 @@ bool loop_close(Loop *loop, bool wait)
|
||||
uv_close((uv_handle_t *)&loop->poll_timer, timer_close_cb);
|
||||
uv_close((uv_handle_t *)&loop->async, NULL);
|
||||
uint64_t start = wait ? os_hrtime() : 0;
|
||||
bool didstop = false;
|
||||
while (true) {
|
||||
uv_run(&loop->uv, UV_RUN_NOWAIT);
|
||||
if (!wait || (uv_loop_close(&loop->uv) != UV_EBUSY)) {
|
||||
// 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, didstop ? UV_RUN_DEFAULT : UV_RUN_NOWAIT);
|
||||
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?");
|
||||
log_uv_handles(&loop->uv);
|
||||
break;
|
||||
}
|
||||
#if defined(EXITFREE)
|
||||
(void)didstop;
|
||||
#else
|
||||
if (!didstop) {
|
||||
// Loop won’t block for I/O after this.
|
||||
uv_stop(&loop->uv);
|
||||
// XXX: Close all (lua/luv!) handles. But loop_walk_cb() does not call
|
||||
// resource-specific close-callbacks, so this leaks memory...
|
||||
uv_walk(&loop->uv, loop_walk_cb, NULL);
|
||||
didstop = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
multiqueue_free(loop->fast_events);
|
||||
multiqueue_free(loop->thread_events);
|
||||
|
||||
Reference in New Issue
Block a user