diff options
| author | Johannes Altmanninger <aclopte@gmail.com> | 2024-12-13 08:24:21 +0100 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2025-06-26 11:23:40 +1000 |
| commit | f0f9d33243224d094e95750b860a636f9e3b0a99 (patch) | |
| tree | 4c1527bf32bd1b0473c7442da35441fee57bdcf5 /test | |
| parent | 6975285dade0d833457bcc36e1bf16d4d92cbb98 (diff) | |
Fix crash on redraw in BufCloseFifo hook
FifoWatcher::read_fifo() deletes the fifo watcher in
m_buffer.values().erase(fifo_watcher_id); // will delete this
which calls: HashMap::unordered_remove()
constexpr_swap(m_items[index], m_items.back());
destructor called here --> m_items.pop_back();
m_index.remove(hash, index);
So hash map invariants (of buffer.values()) are broken, when calling
~FifoWatcher which fires BufCloseFifo hooks. Things blow up if those
hooks access buffer.values() such as by accessing cached highlighters
to redraw the buffer. A shell call with a long sleep in the client
context seems to trigger this.
Fix this by destroying removed map items only at the end of
HashMap::remove(), when invariants are restored. Alternatively, we
could introduce a fifo_trash container; I haven't explored that.
Diffstat (limited to 'test')
| -rw-r--r-- | test/regression/0-slow-BufCloseFifo/cmd | 1 | ||||
| -rw-r--r-- | test/regression/0-slow-BufCloseFifo/in | 1 | ||||
| -rw-r--r-- | test/regression/0-slow-BufCloseFifo/rc | 16 | ||||
| -rw-r--r-- | test/regression/0-slow-BufCloseFifo/script | 2 |
4 files changed, 20 insertions, 0 deletions
diff --git a/test/regression/0-slow-BufCloseFifo/cmd b/test/regression/0-slow-BufCloseFifo/cmd new file mode 100644 index 00000000..2eeea72e --- /dev/null +++ b/test/regression/0-slow-BufCloseFifo/cmd @@ -0,0 +1 @@ +:run<ret> diff --git a/test/regression/0-slow-BufCloseFifo/in b/test/regression/0-slow-BufCloseFifo/in new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/test/regression/0-slow-BufCloseFifo/in @@ -0,0 +1 @@ + diff --git a/test/regression/0-slow-BufCloseFifo/rc b/test/regression/0-slow-BufCloseFifo/rc new file mode 100644 index 00000000..8a953e18 --- /dev/null +++ b/test/regression/0-slow-BufCloseFifo/rc @@ -0,0 +1,16 @@ +define-command run %{ + evaluate-commands %sh{ + mkfifo fifo1 fifo2 2>/dev/null + ( : >fifo1 & ) > /dev/null 2>&1 </dev/null + } + edit! -fifo fifo1 *fifo* + add-highlighter global/myhl regex foo 0:green + hook -once global BufCloseFifo .* %{ + evaluate-commands -client client0 %{ + nop %sh{sleep 2} + } + hook -once buffer NormalIdle .* %{ + echo -to-file fifo2 still alive + } + } +} diff --git a/test/regression/0-slow-BufCloseFifo/script b/test/regression/0-slow-BufCloseFifo/script new file mode 100644 index 00000000..2147a8e8 --- /dev/null +++ b/test/regression/0-slow-BufCloseFifo/script @@ -0,0 +1,2 @@ +mkfifo fifo2 2>/dev/null +assert_eq "$(cat fifo2)" "still alive" |
