Skip to content

pty: Send SIGHUP to foreground process group when master is closed#12855

Open
tanyifeng wants to merge 1 commit intogoogle:masterfrom
tanyifeng:pty-sighup-on-master-close
Open

pty: Send SIGHUP to foreground process group when master is closed#12855
tanyifeng wants to merge 1 commit intogoogle:masterfrom
tanyifeng:pty-sighup-on-master-close

Conversation

@tanyifeng
Copy link
Copy Markdown
Contributor

When the PTY master file descriptor is closed, Linux sends SIGHUP to the foreground process group of the session that has this PTY as its controlling terminal.

gVisor was missing this behavior entirely: closing the master end did not send any signal, causing child processes spawned via PTY to remain running indefinitely instead of being notified of the hangup.

Fix by adding a TTY.Hangup() method that reuses the existing ReleaseControllingTTY() logic to send SIGHUP/SIGCONT and clear the controlling terminal. Call Hangup() for both masterKTTY and replicaKTTY in masterClose().

When the PTY master file descriptor is closed, Linux sends SIGHUP to
the foreground process group of the session that has this PTY as its
controlling terminal.

gVisor was missing this behavior entirely: closing the master end did
not send any signal, causing child processes spawned via PTY to remain
running indefinitely instead of being notified of the hangup.

Fix by adding a TTY.Hangup() method that reuses the existing
ReleaseControllingTTY() logic to send SIGHUP/SIGCONT and clear the
controlling terminal. Call Hangup() for both masterKTTY and replicaKTTY
in masterClose().

Signed-off-by: Tan Yifeng <[email protected]>
@tanyifeng
Copy link
Copy Markdown
Contributor Author

Reproducer

# In a gVisor container — child should be killed when expect exits
docker run --runtime=runsc --rm alpine sh -c '
apk add --no-cache expect procps >/dev/null 2>&1

cat > /tmp/test.exp << "END"
spawn sleep 300
expect timeout
END

expect -f /tmp/test.exp &
PID=$!
sleep 2

SLEEP_PID=$(ps -ef | awk "/sleep 300/ && !/awk|sh -c/ {print \$2}" | head -1)
echo "Sleep PID: $SLEEP_PID"

kill $PID 2>/dev/null
sleep 2

if [ -n "$SLEEP_PID" ] && kill -0 "$SLEEP_PID" 2>/dev/null; then
    echo "BUG: sleep process still running after expect exit"
else
    echo "OK: sleep process terminated"
fi
'

Before fix: sleep 300 remains running after expect exits.
After fix: sleep 300 receives SIGHUP and terminates, matching Linux behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants