Fixes#7500
Supersedes #7582
This commit moves the child exit handling logic from the IO thead to the
apprt thread. The IO thread now only sends a `child_exited` message to
the apprt thread with metadata about the exit conditions (exit code,
runtime).
From there, the apprt thread can handle the exit situation however is
necessary. This commit doesn't change the behavior but it does fix the
issue #7500. The behavior is: exit immediately, show abnormal exit
message, wait for user input, etc.
This also gets us closer to #7649.
Related to #3224
Previously, Ghostty used a static API for async event handling: io_uring
on Linux, kqueue on macOS. This commit changes the backend to be dynamic
on Linux so that epoll will be used if io_uring isn't available, or if
the user explicitly chooses it.
This introduces a new config `async-backend` (default "auto") which can
be set by the user to change the async backend in use. This is a
best-effort setting: if the user requests io_uring but it isn't
available, Ghostty will fall back to something that is and that choice
is up to us.
Basic benchmarking both in libxev and Ghostty (vtebench) show no
noticeable performance differences introducing the dynamic API, nor
choosing epoll over io_uring.