Commit Graph

158 Commits

Author SHA1 Message Date
Justin M. Keyes
ed37136c5c UI: restore 'writedelay' feature.
Removed by e0e41b30c6, probably
unintentionally. Useful for ye olde redraw debugging.

TODO: Also delay redraw of statusline.
2018-02-07 09:25:51 +01:00
Justin M. Keyes
c6fe06bbc0 tui: fix use-after-free after UI stop event #7922
ui_bridge:ui_bridge_stop() calls ui_detach_impl() last, so the check for
ui_active() in ui:ui_refresh() doesn't help: tui_main() already freed
the `ui` object.

There is a race between ui_bridge_stop (thread T0) and tui_main (thread T1).
UIBridgeData.stopped could be set while ui_bridge_stop() is in the
middle of loop_poll_events(), which may invoke tui_scheduler() on T0.
The pointers in tui_scheduler() may be invalid by then.

Solution(?): Use the `UI.data` field as a "stopped" flag and check it in
tui_scheduler().

ASAN use-after-free report observed in #7908:

    = ==20066==ERROR: AddressSanitizer: heap-use-after-free on address 0x611000000cd0 at pc 0x00000182abed bp 0x7ffe23b07070 sp 0x7ffe23b07068
    = READ of size 8 at 0x611000000cd0 thread T0
    =     0 0x182abec in tui_scheduler /home/travis/build/neovim/neovim/src/nvim/tui/tui.c:393:23
    =     1 0x1876afd in ui_bridge_update_fg /home/travis/build/neovim/neovim/build/src/nvim/auto/ui_events_bridge.generated.h:205:3
    =     2 0x186c130 in ui_resize /home/travis/build/neovim/neovim/src/nvim/ui.c:310:3
    =     3 0x146b9c2 in screen_resize /home/travis/build/neovim/neovim/src/nvim/screen.c:7483:3
    =     4 0x186a6f0 in ui_refresh /home/travis/build/neovim/neovim/src/nvim/ui.c:284:3
    =     5 0x186bbe0 in ui_refresh_event /home/travis/build/neovim/neovim/src/nvim/ui.c:297:3
    =     6 0xa2219a in multiqueue_process_events /home/travis/build/neovim/neovim/src/nvim/event/multiqueue.c:150:7
    =     7 0xa1bd7f in loop_poll_events /home/travis/build/neovim/neovim/src/nvim/event/loop.c:63:3
    =     8 0x1872709 in ui_bridge_stop /home/travis/build/neovim/neovim/src/nvim/ui_bridge.c:121:5
    =     9 0x1864247 in ui_builtin_stop /home/travis/build/neovim/neovim/src/nvim/ui.c:143:3
    =     10 0x1249ec8 in mch_exit /home/travis/build/neovim/neovim/src/nvim/os_unix.c:140:3
    =     11 0xe56ba9 in getout /home/travis/build/neovim/neovim/src/nvim/main.c:671:3
    =     12 0xfc4c8f in preserve_exit /home/travis/build/neovim/neovim/src/nvim/misc1.c:2653:3
    =     13 0x1247c02 in deadly_signal /home/travis/build/neovim/neovim/src/nvim/os/signal.c:137:3
    =     14 0x1247921 in on_signal /home/travis/build/neovim/neovim/src/nvim/os/signal.c:162:9
    =     15 0xa35618 in signal_event /home/travis/build/neovim/neovim/src/nvim/event/signal.c:47:3
    =     16 0xa2219a in multiqueue_process_events /home/travis/build/neovim/neovim/src/nvim/event/multiqueue.c:150:7
    =     17 0xa1bd7f in loop_poll_events /home/travis/build/neovim/neovim/src/nvim/event/loop.c:63:3
    =     18 0x1237bd6 in input_poll /home/travis/build/neovim/neovim/src/nvim/os/input.c:349:3
    =     19 0x123334f in inbuf_poll /home/travis/build/neovim/neovim/src/nvim/os/input.c:372:24
    =     20 0x123316d in os_inchar /home/travis/build/neovim/neovim/src/nvim/os/input.c:110:19
    =     21 0x170d20e in state_enter /home/travis/build/neovim/neovim/src/nvim/state.c:55:13
    =     22 0xbd7441 in command_line_enter /home/travis/build/neovim/neovim/src/nvim/ex_getln.c:384:3
    =     23 0xbd0a60 in getcmdline /home/travis/build/neovim/neovim/src/nvim/ex_getln.c:1920:10
    =     24 0xbdb365 in getexline /home/travis/build/neovim/neovim/src/nvim/ex_getln.c:2100:10
    =     25 0xb00a6b in do_cmdline /home/travis/build/neovim/neovim/src/nvim/ex_docmd.c:528:47
    =     26 0x10a7837 in nv_colon /home/travis/build/neovim/neovim/src/nvim/normal.c:4552:18
    =     27 0x1091e15 in normal_execute /home/travis/build/neovim/neovim/src/nvim/normal.c:1136:3
    =     28 0x170d439 in state_enter /home/travis/build/neovim/neovim/src/nvim/state.c:67:26
    =     29 0x104ee14 in normal_enter /home/travis/build/neovim/neovim/src/nvim/normal.c:466:3
    =     30 0xe4295c in main /home/travis/build/neovim/neovim/src/nvim/main.c:572:3
    =     31 0x2b2ba340bf44 in __libc_start_main /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:287
    =     32 0x44d24b in _start (/home/travis/build/neovim/neovim/build/bin/nvim+0x44d24b)
    =
    = 0x611000000cd0 is located 16 bytes inside of 240-byte region [0x611000000cc0,0x611000000db0)
    = freed by thread T1 here:
    =     0 0x4ee0e2 in __interceptor_free /local/mnt/workspace/tmp/ubuntu_rel/llvm/utils/release/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:47:3
    =     1 0xf4f6d4 in xfree /home/travis/build/neovim/neovim/src/nvim/memory.c:133:3
    =     2 0x182a963 in tui_main /home/travis/build/neovim/neovim/src/nvim/tui/tui.c:383:3
    =     3 0x18792b0 in ui_thread_run /home/travis/build/neovim/neovim/src/nvim/ui_bridge.c:106:3
    =     4 0x2b2ba2697183 in start_thread /build/eglibc-ripdx6/eglibc-2.19/nptl/pthread_create.c:312
    =
    = previously allocated by thread T0 here:
    =     0 0x4ee61a in calloc /local/mnt/workspace/tmp/ubuntu_rel/llvm/utils/release/final/llvm.src/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:76:3
    =     1 0xf4f787 in xcalloc /home/travis/build/neovim/neovim/src/nvim/memory.c:147:15
    =     2 0x182000a in tui_start /home/travis/build/neovim/neovim/src/nvim/tui/tui.c:127:12
    =     3 0x1863f7c in ui_builtin_start /home/travis/build/neovim/neovim/src/nvim/ui.c:125:3
    =     4 0xe41bb9 in main /home/travis/build/neovim/neovim/src/nvim/main.c:457:5
    =     5 0x2b2ba340bf44 in __libc_start_main /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:287
    =
    = Thread T1 created by T0 here:
    =     0 0x4d774d in __interceptor_pthread_create /local/mnt/workspace/tmp/ubuntu_rel/llvm/utils/release/final/llvm.src/projects/compiler-rt/lib/asan/asan_interceptors.cc:317:3
    =     1 0x1aae6b0 in uv_thread_create /home/travis/nvim-deps/build/src/libuv/src/unix/thread.c:75
    =     2 0x18217fa in tui_start /home/travis/build/neovim/neovim/src/nvim/tui/tui.c:159:10
    =     3 0x1863f7c in ui_builtin_start /home/travis/build/neovim/neovim/src/nvim/ui.c:125:3
    =     4 0xe41bb9 in main /home/travis/build/neovim/neovim/src/nvim/main.c:457:5
    =     5 0x2b2ba340bf44 in __libc_start_main /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:287

---

Alternative attempt:

    commit 6ad9c02491606a0c31e907f38c9931f324327aa5
    Author: Justin M. Keyes <justinkz@gmail.com>
    Date:   Sat Jan 27 15:12:58 2018 +0100

        tui: fix use-after-free: swap in empty scheduler

        This should make life easier for UIs like VimR which implement their own
        in-process bridged UI: they don't need to worry that their `scheduler`
        might receive an invalid pointer.

        To avoid that, ui_bridge_stopped() swaps in an empty scheduler. Note
        that this requires the call to loop_poll_events() to be moved into the
        critical section.

    diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
    index 779585416f80..491052d19d3b 100644
    --- a/src/nvim/ui_bridge.c
    +++ b/src/nvim/ui_bridge.c
    @@ -93,10 +93,18 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
       return &rv->bridge;
     }

    +static void ui_bridge_null_scheduler(Event event, void *d)
    +{
    +  WLOG("ignoring event (bridge stopped)");
    +}
    +
     void ui_bridge_stopped(UIBridgeData *bridge)
     {
       uv_mutex_lock(&bridge->mutex);
       bridge->stopped = true;
    +  // Replace with an empty scheduler, so that the UI internal scheduler does
    +  // not get invoked with an invalid pointer. #7922
    +  bridge->scheduler = ui_bridge_null_scheduler;
       uv_mutex_unlock(&bridge->mutex);
     }

    @@ -111,14 +119,11 @@ static void ui_bridge_stop(UI *b)
       UIBridgeData *bridge = (UIBridgeData *)b;
       bool stopped = bridge->stopped = false;
       UI_BRIDGE_CALL(b, stop, 1, b);
    -  for (;;) {
    +  while (!stopped) {
         uv_mutex_lock(&bridge->mutex);
         stopped = bridge->stopped;
    -    uv_mutex_unlock(&bridge->mutex);
    -    if (stopped) {
    -      break;
    -    }
         loop_poll_events(&main_loop, 10);  // Process one event (at most).
    +    uv_mutex_unlock(&bridge->mutex);
       }
       uv_thread_join(&bridge->ui_thread);
       uv_mutex_destroy(&bridge->mutex);
2018-01-28 03:08:04 +01:00
Björn Linse
34057045be ui: forward relevant option updates to UIs (#7520)
also make termguicolors mutable after startup
2017-12-12 18:23:19 +01:00
Björn Linse
06fd32b8ff ui: remove ext_cmdline noise (#7486)
Only send cmdline contents once per ui_flush.
Don't send extra redraws due to 'arshape', it makes no difference to
external ui.
2017-11-07 18:53:42 +01:00
Matthieu Coudron
e3a2cca387 Increased test coverage for RGB and cterm 2017-09-30 11:43:26 +09:00
Matthieu Coudron
ba7277cfb4 Adds nvim_get_hl_by_name/by_id
...in order to retrieve highlights.

Added test/functional/api/highlight_spec.lua
HL_NORMAL is not really a good name, since it's more like an empty attribute than the normal's one.
If one pays attention, syn_cterm_attr2entry is never called with attr=0 because it's always special cased before.
I suggest in subsequent PRs we remove the ATTR_OFF and just insert an EMPTY ATTR/RESET_ATTR/UNINITIALIZED for id 0.
2017-09-30 11:43:26 +09:00
Justin M. Keyes
63c6470505 log: introduce context 2017-09-05 15:01:07 +02:00
Justin M. Keyes
34e5654f21 ui: disable 'lazyredraw' during ui_refresh.
Could also try `do_redraw = true` instead of save/restore `p_lz`, but
the nice thing about save/restore of `p_lz` is that it is "atomic".
The semantics of `do_redraw` are not clear to me.

Closes #4884
References #6202
References https://github.com/neovim/neovim/pull/6202#issuecomment-284379503
References #3929 #5692 #6157
References #5866
2017-08-14 03:07:50 +02:00
Justin M. Keyes
13f5bc9586 log: all UI events, not just UI-bridge
Rename ui_bridge.c:UI_CALL to UI_BRIDGE_CALL.
2017-07-22 21:26:03 +02:00
Björn Linse
7d6af9985c ui: cleanup UI_CALL wrappers
remove pointless control chars in the text stream
2017-05-10 16:14:12 +02:00
Björn Linse
489d10c57c api: generate ui events 2017-05-10 16:14:10 +02:00
Justin M. Keyes
8f59d14839 event: Remove "priority" concept.
It was replaced by the "child queue" concept (MultiQueue).
2017-04-28 19:20:09 +02:00
Justin M. Keyes
00843902d3 api/ui: externalize tabline
- Work with a bool[] array parallel to the UIWidget enum.
- Rename some functions.
- Documentation.
2017-04-26 03:41:24 +02:00
Dongdong Zhou
88023d5123 api/ui: externalize tabline 2017-04-26 02:15:31 +02:00
Justin M. Keyes
10f119ab87 Merge #6539 'More cursor shape modes' 2017-04-21 19:09:50 +02:00
Björn Linse
7ea5c78687 ui: use an array for mode styles 2017-04-21 12:32:38 +02:00
Björn Linse
9cdbbd4982 ui: support more cursor shape modes
throttle unneccessary cursor shape events
2017-04-21 12:32:38 +02:00
ZyX
c2f3e361c5 *: Add comment to all C files 2017-04-19 19:11:50 +03:00
Justin M. Keyes
3ccd59ee82 'guicursor': enabled=false if 'guicursor' is empty
Closes #6429
Closes #6430
2017-04-04 14:19:26 +02:00
Matthieu Coudron
dd4a5fcbb6 tui: 'guicursor' shape #6044
Closes #2583
2017-04-01 23:14:05 +02:00
Tommy Allen
6777b6ecbc ui: Fix TUI resize bug
statusline still disappears in some cases, but this change is a net
improvement.

References #3929 #5692 #4884 #6157
2017-03-05 22:17:32 +01:00
Justin M. Keyes
59f12e7d61 ui_detach: Do not redraw during teardown/exit. 2017-02-14 00:33:52 +03:00
Justin M. Keyes
043f85210a tui: "backpressure": Drop messages to avoid flooding.
Closes #1234

multiqueue:
- Implement multiqueue_size()
- Rename MultiQueueItem.parent to MultiQueueItem.parent_item, to avoid confusion
  with MultiQueue.parent.
2016-12-09 18:51:17 +01:00
Björn Linse
1f8a3da796 Merge pull request #5669 from chemzqm/add-cmdline-mode-rpc
Add cmdline mode to ui_mode_change
2016-12-01 08:05:44 +01:00
chemzqm
3cf4b14e96 add cmdline mode to modechange of RPC and tests
use set_cursor_shape_bar for cmdline mode

fix test of screen_basic_spec.lua & screen.lua

comment fix
2016-11-30 22:20:06 +08:00
Justin M. Keyes
7be113d795 shell_write_cb: Schedule error message. (#5670)
Closes #5558
2016-11-26 13:08:42 +01:00
James McCoy
68f7464eed ui: Blank the next cell for any multi-cell character
Followup for #5461
2016-10-12 16:32:53 -04:00
James McCoy
892f55bd20 ui: Fix the call to utf_ambiguous_width
`utf_ambiguous_width` expects the Unicode character, but in 9e1c6596 I
just passed the first UTF-8 byte to the function.  This led to various
display problems because now many multi-cell characters weren't falling
into that part of the branch.

Also, to better align with the existing Vim code, remove the forced
cursor update.  Setting the flag will cause it to happen in the next
UI_CALL.

Thanks to qvacua for all the help investigating the issue!

Closes #5448
2016-10-11 18:59:01 -04:00
James McCoy
9e1c659666 vim-patch:7.4.1697
Problem:    Display problems when the 'ambiwidth' and 'emoji' options are not
            set properly or the terminal doesn't behave as expected.
Solution:   After drawing an ambiguous width character always position the
            cursor.

cb0700844c
2016-09-24 15:02:51 -04:00
Justin M. Keyes
b94891421a ui_detach: Schedule refresh on main loop.
Closes #4163
2016-09-22 20:04:32 +02:00
Justin M. Keyes
df072c3b2b refactor: eliminate misc2.c
move `call_shell` to misc1.c
Move some fns to state.c
Move some fns to option.c
Move some fns to memline.c
Move `vim_chdir*` fns to file_search.c
Move some fns to new module, bytes.c
Move some fns to fileio.c
2016-09-13 16:20:09 +02:00
Björn Linse
e968d72cae api/ui: use ui options instead of one method per feature
Use new nvim_ui_ prefix to avoid breaking change.
2016-08-29 10:17:31 +02:00
Björn Linse
999af47be8 api/ui: allow popupmenu to be drawn by external ui 2016-08-29 10:17:31 +02:00
ZyX
ce234b0da5 *: Fix new linter errors 2016-06-11 00:08:58 +03:00
ZyX
d359bb3f60 *: Fix errors from new linter checks 2016-06-11 00:08:57 +03:00
Justin M. Keyes
f5642a171f Merge pull request #4817 from bfredl/remoteui
api: refactor remote ui to use API dispatch generation
2016-05-27 20:58:14 -04:00
Rui Abreu Ferreira
46aac2a09a Windows: Don't build the TUI is systems where it is not supported
The TUI can be enabled/disabled at build time with -DFEAT_TUI, default is ON for
UNIX, and OFF for non UNIX. When off, Neovim prints a message to stderr, along
with a list of the server endpoints.
2016-05-27 23:43:40 +01:00
Björn Linse
dd539366fc api: refactor remote ui to use API dispatch generation 2016-05-27 13:18:04 +02:00
AdnoC
244cfe86b5 syntax: Add support for the "special" color used for undercurls 2016-05-17 16:31:42 -04:00
Rui Abreu Ferreira
c5d0c280d3 MSVC: Fix UI_CALL macro for MSVC.
The UI_CALL macro uses variadic macros and relies on the non standard
GCC extension. MSVC already applies similar behavior for the regular
__VA_ARGS__ removing the comma.
In MSVC UI_CALL can be implemented by calling UI_CALL_MORE directly.
2015-12-22 09:35:34 -05:00
Björn Linse
fa5827b144 encoding: simplify handling of encoding in TUI 2015-09-08 10:53:44 +02:00
Robin Allen
d5b5063622 Notify attached UIs whenever menus change
This adds a redraw notification "update_menu" which is sent whenever
Vim's menus are changed by the :menu command and friends.
2015-08-21 14:23:50 +01:00
Thiago de Arruda
502aee690c event: Refactor async event processing
- Improve the implementation of deferred/immediate events.
- Use the new queue module to change how/when events are queued/processed by
  giving a private queue to each emitter.
- Immediate events(which only exist to break uv_run recursion) are now
  represented in the `loop->fast_events` queue.
- Events pushed to child queues are propagated to the event loop main queue and
  processed as K_EVENT keys.
2015-08-13 08:49:38 -03:00
Omar Sandoval
f79025b9de tui: Use underline cursor in Replace mode
This is a port of my original contribution to Vim, added in 7.4.687
(https://github.com/vim/vim/commit/v7-4-687). The TUI code has been
heavily refactored (see esp. 25ceadab37),
so this required some translation, but the logic is the same.
2015-07-26 23:45:41 -04:00
Omar Sandoval
fa48fc667a api: Simplify UI API on mode change
Currently, there are two functions in the UI API that are called when
the mode changes: insert_mode() and normal_mode(). These can be folded
into a single mode_change() entrypoint which can do whatever it wants
based on the mode it is passed, limited to INSERT and NORMAL for now.
2015-07-26 23:38:35 -04:00
Thiago de Arruda
991d3ec1e6 event loop: New abstraction layer with refactored time/signal API
- Add event loop abstraction module under src/nvim/event. The
  src/nvim/event/loop module replaces src/nvim/os/event
- Remove direct dependency on libuv signal/timer API and use the new abstraction
  instead.
- Replace all references to uv_default_loop() by &loop.uv, a new global variable
  that wraps libuv main event loop but allows the event loop functions to be
  reused in other contexts.
2015-07-17 00:19:19 -03:00
Björn Linse
80d61fb87b tui: make termkey use utf-8 mode when &encoding=utf-8 #2469 2015-06-13 19:49:25 +02:00
Thiago de Arruda
05d60c4812 ui: Schedule screen refreshs to run in the event loop
This is required to avoid event loop recursion due to indirect calls to
os_breakcheck by screenalloc
2015-03-25 18:57:35 -03:00
Thiago de Arruda
8b7b71f474 ui: Refactor so that busy state won't be the default
Even though assuming nvim is busy most times is simpler, it has a problem: A lot
of unnecessary busy_start/busy_stop notifications are sent to the UI. That's
because in the majority of scenarios almost no time is spent between
`event_poll` calls.

This restores the normal behavior which is to call busy_start only when nvim is
going to perform some task that can take a significant amount of time. Also
improve the usage of buffering in the TUI when changing the cursor state.
2015-03-18 14:16:23 -03:00
Thiago de Arruda
1d80c0e3a0 ui: Only call ui_flush when the busy state changes
Also add back the `ui_flush` call to `get_keystroke`. Its necessary to display
prompt messages correctly.
2015-03-16 08:35:43 -03:00