A terminal with lots of scrollback history will have allocated a lot
of memory.
Normally, free() wont return this memory to the OS, and we don't seem
to trigger the automatic trim calls.
This means the server would accumulate quite a lot of memory over
time, as terminals come and go.
Now we explicitly trim the memory every time a terminal is destroyed.
Make ptmx non-blocking. Then, when writing data to the slave would
have blocked, use the FDM to asynchronously write the remaining data.
This is done by enabling EPOLLOUT on ptmx, and enqueueing all outgoing
data. The FDM handler will go through the enqueued data, and once all
of it has been written, we turn off EPOLLOUT again (thus switching
back to synchronous writes)
When checking of a 'foot --server' instance is already running, we try
to connect to the UNIX socket we're planning on listening on.
In most cases, this will fail hard and fast. But under certain
circumstances, we can get stuck in connect() waiting for a connection
timeout.
Since it should be possible to establish a connection immediately *if*
there's someone actually listening on the socket, rely on the fact
that connect() will fail with a EINPROGRESS if a connection can *not*
be established immediately (and thus no one is listening on it).
Since fonts are cached, this adds no additional memory. However, it
makes the first terminal window in --server mode start much faster,
since the (primary) fonts have already been loaded.
Fallback fonts are still loaded on-demand.
While unusual, it *is* possible for a client *not* to terminate when
we close ptmx.
We need to handle this *somehow*. Since it is so unusual, we'll go
with a fairly easy, but synchronous method:
* Register a signal handler for SIGALRM, and setup a 2 second alarm
* Wait for slave to die
* If it didn't die, sent SIGTERM, then re-set the alarm for another 2
seconds.
* If it still hasn't died, send SIGKILL (this time without an alarm).
When there hasn't been a timeout (or in our case, there was a timeout,
but we reset the timer before we got to the read()), read() returns,
not 0, but -1 with errno == EAGAIN.