This fixes an issue where we ended up "double closing" buffer FDs.
In many cases (especially on compositors with SSDs) this was pretty
rare. And even when it did happen, the FD was normally unused, and
thus nothing bad happened.
However, by quickly resizing the window while using CSDs, it was
fairly easy to trigger this. We sometimes ended up closing the
TIOCSWINCH timer FD while thinking it was a buffer FD, but most of the
times we just ended up closing _another_ buffer’s pool FD, leading to
an immediate disconnect by the compositor.
There’s a chance the resize timeout FD was closed, and *reused*, after
epoll() told us the FD is readable, but before our callback runs.
Thus, closing the FD provided as an argument is dangerous, as it may
refer to something completely different.
When tagging URL cells (in preparation for rendering URL mode), we
loop the URL’s entire range, setting the `url` attribute of all cells,
and dirtying the rows.
It is possible to create URLs that are invalid, and wrap around the
scrollback, even though the scrollback hasn’t yet been filled. For
example, by starting an OSC-8 URL, moving the cursor, and then closing
the OSC-8 URL.
These URLs are invalid, but are still rendered just fine. “Fine” being
relative - they will typically fill the entire screen. But at least
that’s a very clear indication for the user that’s something is wrong.
The problem is when we hit un-allocated scrollback rows. We didn’t
check for NULL rows, and crashed.
This has now been fixed.
The only reason to keep the pool FD open is if we’re going to SHM
scroll the buffer; we need the FD for fallocate(FALLOC_FL_PUNCH_HOLE).
In all other cases, there’s absolutely no need to keep the FD
open. Thus, close it as soon as we’ve instantiated the buffer. This
frees up FDs, and help keep foot from FD ulimit.
Removing overlaping and duplicated URLs is done by running two nested
loops, that both iterate the same URL list.
When a duplicate is found, one of the URLs is destroyed and removed
from the list.
Deleting and removing an item *is* safe, but only as long as _no
other_ iterator has references to it.
In this case, if we remove an item from e.g. the inner iterator, we’ll
crash if the outer iterator’s *next* item is the item being removed.
Closes#627
All SHM pixmap cookies depend on the terminal instance’s memory
address. Thus, after a terminal instance has been destroyed, shm
pixmaps that belonged to it will never be purged automatically.
CSDs aren’t typically toggled on and off. Thus, when disabled,
immediately purge their corresponding pixmap buffers, to free up some
memory, and release file descriptors.
Unlike other surface types, the SHM cookie depends on the address of
each URL instance. This means if we enable, disable, and then enable
URL mode again (thus showing exactly the same URLs as the first time),
the URLs will have new addresses, and thus the old SHM pixmaps will
not get purged automatically.
So, manually purge them when destroying the URLs.
That is, instead of requiring a ‘\n’ to be printed, non-empty lines
are now treated as having a hard linebreak by default.
The linebreak is cleared on an explicit wrap.
A narrow, but offset:ed glyph should still be considered double
width.
This patch also fixes a crash, when the maybe-double width glyph is in
the last column. This is a regression.
All emoji graphemes are double-width. Foot doesn’t support non-latin
scripts. Ergo, this should result in the Right Thing, even though
we’re not doing it the Right Way.
Note that we’re now breaking cursor synchronization with nearly all
applications.
But the way I see it, the applications need to be
updated.
We’re mainly interested in seeing that we don’t leak memory, or double
free heap allocated data.
Valgrind and/or gcc/clang sanitizers are best at this, hence the very
few asserts in the test itself.
Instead of keeping removed/replaced key bindings in the key binding
array (marked as ‘unused’), remove them, by compacting the array.
The invariant is thus that there should be *no* entries in the key
binding list with the `BIND_ACTION_NONE` for action.
Add code to debug builds that verifies this, plus a unit test.
Closes#614
These extensions are used by tmux and neovim, in order to make use
of 24-bit colors without facing the problems that plague the `RGB`
capability.
This should allow 24-bit colors to work "out of the box" in tmux,
without the usual workaround of adding:
set-option -ga terminal-overrides ",foot*:Tc"
...to ~/.tmux.conf.
See also:
* 18fe2e8dfa (commitcomment-31373962)
* f83c25942d/runtime/doc/term.txt (L123-L139)
* b1a8c0fe02/CHANGES (L988-L989)Closes#615
This means that logging will be completely disabled until log_init()
has been called, which is useful to prevent log spam when running
UNITTEST{} blocks in debug builds.
Note that this doesn't change the default log level at runtime, which
was already being set to LOG_CLASS_INFO in main.c and client.c.
The new log level is also exposed to the command-line interface as
`--log-level=none`, which allows disabling logging entirely.