Make sure we don't close virtual term FDs too early.
Avoid a double-delete of threads from a process.
Avoid a deadlock when exiting.

When clearing the message queue, we send a notification to the main
thread, but if the main thread was not waiting on the condition variable
at that time, the notification is lost. The main thread re-enters the
wait and gets stuck there.
Join the redirector thread before exiting.

If a non-detached std::thread is destroyed before being joined, it is
terminated with std::terminate.