Skip to content

Prevent setup PTY test children from surviving a dead test harness #736

Closed

Description

@JacobStephens2

This was generated by AI during triage.

Historical observation

During the 2026-10-16 triage session, 24 target/debug/thirdshift setup processes from several integration-test worktrees were found idle on PTYs for approximately 10–16 days. They were ended at the maintainer's direction. This report records that observation; those processes are no longer available for inspection, and no live reproduction was performed during this triage.

Current code and uncertainty

tests/support/mod.rs::Scenario::run_terminal creates a PTY and starts the child in a new session using setsid() and TIOCSCTTY. It wraps the child in TerminalCommand, whose Drop kills and waits for that immediate child. The fixture also bounds ordinary prompt and exit waits.

That cleanup should cover an assertion panic that unwinds normally. It cannot execute after abrupt death of the test-harness process. The historical observation is consistent with missing cleanup on harness death, but it does not establish which signal or lifecycle event originally left these children alive. Do not treat normal panic cleanup as wholly absent.

Requested outcome

Reproduce the lifecycle gap with a small isolated fixture that starts an actual setup PTY child, ends only its own fixture harness, and checks that no owned setup process remains. Cover ordinary completion, assertion unwinding, a bounded timeout, and abrupt harness termination separately. Establish the supported-platform cleanup contract before choosing a mechanism; clean up only fixture-owned processes and reap children where possible.

The resulting fix should keep setup's terminal behavior and existing interruption/terminal-restoration assertions intact. Report any platform limitations explicitly. Avoid blanket process-name kills or broad cleanup of temporary directories.

Related issues

Activity

  1. JacobStephens2 commented on Oct 21, 2026

    @JacobStephens2
    OwnerAuthor

    This was generated by AI during triage.

    Agent Brief

    Category: bug
    Summary: A thirdshift setup child started on a test PTY never outlives its test

    Current behavior:
    The integration-test fixture that drives thirdshift setup interactively opens a PTY. It starts setup as a new session leader with the PTY as its controlling terminal, and wraps it in a guard that kills and reaps it when dropped. That covers a test that returns or unwinds normally. Nothing ends the child if the test process itself dies abruptly.

    Setup records SIGHUP, SIGINT and SIGTERM as an interruption rather than dying on them. Its input polling then ends it, as it does when stdin closes.

    On 2026-10-16, 24 thirdshift setup processes from integration-test worktrees were found idle on PTYs, 10–16 days after their tests, and were ended by hand. They weren't inspected, so what left them is unknown. A closed PTY master would hang up the terminal and end setup, so idle children suggest the master stayed open, for example through an inherited descriptor, or that their test process never exited.

    Desired behavior:
    A setup child started by the fixture ends when its test ends, however the test ends: normal completion, a failed assertion, a timeout, or abrupt death of the test process (SIGKILL). Cleanup acts only on processes the fixture started. Setup's terminal behavior is unchanged, and so are the existing interruption and terminal-restoration tests.

    Key interfaces:

    • The terminal fixture (Scenario::run_terminal) and its child guard (TerminalCommand).
    • Inheritance of the PTY descriptors (close-on-exec on master and slave), and the child's session and process group.
    • Setup's interruption handling while it waits for input, but only if the investigation shows setup itself fails to end on a hung-up terminal.

    Acceptance criteria:

    • A regression test runs the fixture in a separate harness process, starts a real setup PTY child there, kills that harness with SIGKILL, and checks that the setup child is gone within a bound. Reproduce against current code first and say in the PR whether the test failed before the change. If it already passes, keep it as a guard and say so.
    • Normal completion, a failed assertion and a timeout each leave no setup child behind.
    • Nothing is killed by process name, and no temporary directory is cleaned up beyond what the fixture owns.
    • Linux is covered. On macOS the test passes, or is skipped with the platform limit named.

    Out of scope:

  2. added
    ready-for-agentFully specified, ready for an AFK agent
    in-progressA Claim: thirdshift has taken this issue
    and removed
    needs-triageMaintainer needs to evaluate this issue
    ready-for-agentFully specified, ready for an AFK agent
    on Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions