widget: Fix race between polling the master & using the PTY in a child
Unlike its synchronous variant, vte_terminal_spawn_async
starts polling the pseudo-terminal master device before forking and exec-ing the child process.
This is not a bug in VTE as it stands today. (See bug 794047) However, it causes a race in downstreams like Red Hat Enterprise Linux 7 that continue to use gnome-pty-helper
to avoid changing the feature set in a stable release.
When gnome-pty-helper
is used, the helper is in charge of creating the pseudo-terminal device pair, and it closes its copies of the file descriptors after sending them to the main UI process. If VteTerminal
starts polling the master device immediately after receiving it from the helper, before the child process has been forked, and the helper loses the race to close its copy of the slave device's file descriptor before the master is polled, then VteTerminal
will receive a G_IO_HUP
and stop reading further input from the master. The subsequently forked child process gets left in a defunct state and this CRITICAL
is logged:
Vte-CRITICAL **: void vte_terminal_watch_child(VteTerminal*, GPid) assertion 'impl->m_pty != NULL' failed
Instead, if VteTerminal
starts polling the pseudo-terminal master after the child process has been set up, then the race is avoided. The child keeps its copy of the slave file descriptor open and it prevents VteTerminal
from receiving any G_IO_HUP
even if the helper closes its copy afterwards.