aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago de Arruda <tpadilha84@gmail.com>2015-10-31 07:36:08 -0300
committerThiago de Arruda <tpadilha84@gmail.com>2015-10-31 08:03:49 -0300
commit0dac6660985dee7c5515b9b5a91e4ed66d151bc2 (patch)
tree1cc7247e35c4aa46a433f1a632998155c09e2948
parentef1d39bbbf960d0b9f07aee333a34239d430a4db (diff)
downloadrneovim-0dac6660985dee7c5515b9b5a91e4ed66d151bc2.tar.gz
rneovim-0dac6660985dee7c5515b9b5a91e4ed66d151bc2.tar.bz2
rneovim-0dac6660985dee7c5515b9b5a91e4ed66d151bc2.zip
ui_bridge: Fix race condition that results in deadlock.
Fixed by waiting until the UI thread finishes processing events. Close #3541.
-rw-r--r--src/nvim/tui/tui.c1
-rw-r--r--src/nvim/ui_bridge.c19
-rw-r--r--src/nvim/ui_bridge.h4
3 files changed, 23 insertions, 1 deletions
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index c5f2950e62..02efa1f8df 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -219,6 +219,7 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
loop_poll_events(&tui_loop, -1);
}
+ ui_bridge_stopped(bridge);
term_input_destroy(&data->input);
signal_watcher_stop(&data->cont_handle);
signal_watcher_close(&data->cont_handle, NULL);
diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
index 836339a887..359fffe3bf 100644
--- a/src/nvim/ui_bridge.c
+++ b/src/nvim/ui_bridge.c
@@ -74,6 +74,13 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
return &rv->bridge;
}
+void ui_bridge_stopped(UIBridgeData *bridge)
+{
+ uv_mutex_lock(&bridge->mutex);
+ bridge->stopped = true;
+ uv_mutex_unlock(&bridge->mutex);
+}
+
static void ui_thread_run(void *data)
{
UIBridgeData *bridge = data;
@@ -82,8 +89,18 @@ static void ui_thread_run(void *data)
static void ui_bridge_stop(UI *b)
{
- UI_CALL(b, stop, 1, b);
UIBridgeData *bridge = (UIBridgeData *)b;
+ bool stopped = bridge->stopped = false;
+ UI_CALL(b, stop, 1, b);
+ for (;;) {
+ uv_mutex_lock(&bridge->mutex);
+ stopped = bridge->stopped;
+ uv_mutex_unlock(&bridge->mutex);
+ if (stopped) {
+ break;
+ }
+ loop_poll_events(&loop, 10);
+ }
uv_thread_join(&bridge->ui_thread);
uv_mutex_destroy(&bridge->mutex);
uv_cond_destroy(&bridge->cond);
diff --git a/src/nvim/ui_bridge.h b/src/nvim/ui_bridge.h
index 76e9e27989..31b9a69216 100644
--- a/src/nvim/ui_bridge.h
+++ b/src/nvim/ui_bridge.h
@@ -22,6 +22,10 @@ struct ui_bridge_data {
// the call returns. This flag is used as a condition for the main
// thread to continue.
bool ready;
+ // When a stop request is sent from the main thread, it must wait until the UI
+ // thread finishes handling all events. This flag is set by the UI thread as a
+ // signal that it will no longer send messages to the main thread.
+ bool stopped;
};
#define CONTINUE(b) \