Skip to content

tests: pty_run flakes when stdin isn't a terminal — 'script: tcgetattr/ioctl: Operation not supported on socket' #207

Description

@martin-conur

Problem

pty_run (added in #198 to regression-test the tty branch of cmd_unregister) fails when
the invoking shell's stdin is not a terminal — which is the normal case inside an agent
harness, a CI step, or any piped invocation:

script: tcgetattr/ioctl: Operation not supported on socket

Observed 2026-09-14: 3 failures in radio_lifecycle.bats's #198 pty tests during a local
full-suite run under an agent worker. They pass in isolation (61/61), pass on a clean
re-run (1013/1013), and CI is green on both runners — so it is intermittent, environment-
dependent, and not a product defect.

Why it's worth fixing rather than tolerating

A flaky test in the suite that verifies radio is corrosive in a specific way: it trains
whoever runs it to discount red. Today a worker correctly diagnosed it as pre-existing and
out of scope — the next one may instead spend a round chasing it, or worse, learn to
re-run until green. That habit is exactly what would have hidden #203.

BSD script (macOS) and util-linux script (Linux) both want a real tty on stdin to
allocate the pty. The helper already handles the syntax difference between the two; it
does not handle the precondition that stdin be a terminal.

Fix options

  1. Give script a tty on stdin — < /dev/tty where available, so the helper doesn't
    depend on inheriting one.
  2. Skip with a reason when no pty can be allocated. bats' skip is honest and keeps
    the suite green in harnesses that genuinely cannot provide one; CI (which can) still
    exercises the branch, so coverage isn't lost where it matters.
  3. Both — prefer a real pty, skip explicitly when one is unobtainable.

(3) is the shape that keeps the signal and drops the noise. A silent skip would be worse
than the flake, so whichever path is taken the reason must be printed.

Acceptance

Notes

Found by the #191 worker during an intermediate full-suite run; correctly scoped out of
that PR since it touches neither pty_run nor radio_lifecycle.bats. Pre-existing
fragility introduced with #198, not a regression from #203/#191.

Activity

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