Skip to content

fix: handle disconnected launcher output - #135

Open
andreivince wants to merge 3 commits into
ActivityWatch:masterfrom
andreivince:codex/aw-828-launcher-output
Open

andreivince wants to merge 3 commits into
ActivityWatch:masterfrom
andreivince:codex/aw-828-launcher-output

Conversation

@andreivince

@andreivince andreivince commented Oct 4, 2026 •

Copy link
Copy Markdown

Repairs disconnected stdout/stderr before startup, including terminals and pipes, so modules and the tray's Dashboard/Quit actions keep working. Healthy output stays unchanged.

Fixes ActivityWatch/activitywatch#828.

Adds a regression to make test. Linux and isolated macOS suites pass (122 tests each), plus mypy and ten macOS package checks. Flake8 has the same four existing W503 warnings. Haven't tested live KRunner or Windows.

Copilot AI balanced review requested due to automatic review settings October 4, 2026 19:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@greptile-apps

greptile-apps Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

[Medium risk] Adds output stream repair to the application startup path.

The PR is not safe to merge until startup also handles disconnected pipes that pass the zero-length probe.

Findings

  1. P1 Disconnected pipes go undetected ▶
  2. P2 Regression test misses CI ▶

Summary

The PR probes stdout and stderr at startup and redirects descriptors it detects as unusable to the null device. It adds a subprocess regression test covering managed-module output and tray actions.

  • A disconnected pipe can pass the zero-length probe, leaving the reported failure possible.
  • The new regression test is not included in CI’s test commands.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Desktop launch] --> B[Zero-length output probe]
  B -->|Raises OSError| C[Redirect descriptor to null device]
  B -->|Returns zero on pipe without reader| D[Keep broken descriptor]
  D --> E[Tray or managed module writes data]
  E --> F[BrokenPipeError]
Loading

Reviews (1) · Last reviewed commit: "fix: handle disconnected launcher output"

Comment thread aw_qt/main.py Resolved
Comment thread tests/test_main.py Resolved

@TimeToBuildBob TimeToBuildBob left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed. Redirecting a dead fd 1/2 to /dev/null before any module is spawned is the right repair point for ActivityWatch/activitywatch#828, since children inherit the fixed descriptors. The closed-fd edge case (os.open reusing the same number) is handled too.

One likely regression to check before merge, on macOS with a healthy terminal. Apple's poll(2) doesn't support device files and reports POLLNVAL for tty fds. With poller.register(fd, 0), any returned event marks the fd unusable. So aw-qt launched normally from Terminal.app would probably get its stdout and stderr silenced. The macOS suite most likely didn't see this because pytest's stdout is a pipe, not a tty.

Suggested fix: count only POLLERR | POLLHUP as unusable and ignore POLLNVAL, e.g.

events = poller.poll(0)
unusable = any(ev & (select.POLLERR | select.POLLHUP) for _, ev in events)

On macOS a disconnected tty then isn't repaired by the probe. That still beats losing output on every healthy launch, and pipes, the common launcher case, still get POLLERR/POLLHUP. A quick manual check (aw-qt --testing from Terminal.app, confirm log output still appears) would settle it.

CI hasn't run yet: the fork's runs are held action_required and need maintainer approval.

@andreivince

Copy link
Copy Markdown
Author

@TimeToBuildBob I tested this on macOS 26.6.2 and couldn't reproduce the output being silenced.

I did get POLLNVAL from /dev/tty when requesting read/write events. With poller.register(fd, 0), though, I got no events and stdout/stderr kept working. The existing tests passed too, including the broken-descriptor cases.

I'm leaving the code as it is for now. The terminal checks used PTYs. I haven't checked a manual Terminal.app launch or older macOS versions.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor

Thanks for testing. poller.register(fd, 0) requesting zero events is the key — POLLNVAL only fires when you ask for events on an unsupported fd type, not when the mask is empty. macOS returning nothing for a healthy tty with mask 0 is exactly right, so the fix leaves healthy terminals untouched. My concern is resolved.

The Greptile P1 (pipe-without-reader undetected) and P2 (test missing from CI) look addressed too (6b83cb2 adds the closed-pipe cases and wires pytest into make test).

The one remaining gap is CI: the fork's runs appear held at action_required, so there's no green check from the full suite. That's a maintainer click to approve the workflow run. Once CI passes, the PR looks merge-ready from my side.

@TimeToBuildBob

Copy link
Copy Markdown
Contributor

The merge commit today (cc82b40) brings the branch up to date with master. The core _ensure_output_streams() function is unchanged from my earlier review, and the conflict resolution in tests/test_main.py correctly incorporates both the existing master tests and this PR's new regression cases.

Everything still looks good on the code side. The only remaining blocker is CI: the fork's workflow runs are held at action_required again after this push. Approving them requires admin access. @ErikBjare — a click to approve the fork's workflow run would unblock the final CI check.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Linux: [Errno 5] Input/output error (aw_server.server:122) when starting-up aw-qt

3 participants