diff options
| author | Thiago de Arruda <tpadilha84@gmail.com> | 2015-10-31 07:36:08 -0300 | 
|---|---|---|
| committer | Thiago de Arruda <tpadilha84@gmail.com> | 2015-10-31 08:03:49 -0300 | 
| commit | 0dac6660985dee7c5515b9b5a91e4ed66d151bc2 (patch) | |
| tree | 1cc7247e35c4aa46a433f1a632998155c09e2948 /src | |
| parent | ef1d39bbbf960d0b9f07aee333a34239d430a4db (diff) | |
| download | rneovim-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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/tui/tui.c | 1 | ||||
| -rw-r--r-- | src/nvim/ui_bridge.c | 19 | ||||
| -rw-r--r-- | src/nvim/ui_bridge.h | 4 | 
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)                                                    \ | 
