Repository navigation
Conversation
Picker thumbnails await ScreenCaptureKit's shareable content and each SCScreenshotManager screenshot with no timeout. When one request never answers, the sweep's blocking thread parks for good, the inflight flag is never cleared, and display thumbnails stop refreshing for the rest of the session (the launch prewarm never reaches windows either). Bound each of those requests by 5s. A timeout ends the sweep, so its channel closes and inflight resets, and pauses thumbnail captures for 5 minutes: a hung request cannot be cancelled and holds macOS's capture session open in replayd, so retrying on every picker poll would only stack more of them. The sweep's runtime now enables the timer driver that tokio::time::timeout needs. This does not end a request that is already stuck inside replayd, so it cannot clear a stuck screen-recording indicator by itself. Refs CapSoftware#2339
| else { | ||
| return; |
There was a problem hiding this comment.
A timed-out window sweep still gets marked as complete. It sends WindowEvent::Listed before this early return, and the receiver saves that list’s signature when the channel closes. With an unchanged window list, windows_stale() then stays false, so thumbnails do not retry after the five-minute pause or when the picker reopens.
Keep interrupted sweeps stale so they can retry after the pause.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop-gpui/src/target_thumbnails.rs
Line: 647-648
Comment:
**Window thumbnails never retry**
A timed-out window sweep still gets marked as complete. It sends `WindowEvent::Listed` before this early return, and the receiver saves that list’s signature when the channel closes. With an unchanged window list, `windows_stale()` then stays false, so thumbnails do not retry after the five-minute pause or when the picker reopens.
Keep interrupted sweeps stale so they can retry after the pause.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Fixed in 7d12f22. Both sweep receivers now save the list signature only when captures aren't paused, so a sweep cut short by a hang leaves the list stale and gets retried once the pause ends.
| assert!(!pause.active_at(now)); | ||
| pause.start_at(now); | ||
| assert!(pause.active_at(now)); | ||
| assert!(pause.active_at(now + CAPTURE_HANG_PAUSE - Duration::from_millis(1))); |
There was a problem hiding this comment.
Test breaks time subtraction rule
The new assertion subtracts time directly. AGENTS.md requires saturating_sub() instead of a - b for Duration and Instant. Use (now + CAPTURE_HANG_PAUSE).saturating_sub(Duration::from_millis(1)) here. This repository requirement must be satisfied before merging.
| assert!(pause.active_at(now + CAPTURE_HANG_PAUSE - Duration::from_millis(1))); | |
| assert!(pause.active_at((now + CAPTURE_HANG_PAUSE).saturating_sub(Duration::from_millis(1)))); |
Context Used: AGENTS.md (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop-gpui/src/target_thumbnails.rs
Line: 1574
Comment:
**Test breaks time subtraction rule**
The new assertion subtracts time directly. `AGENTS.md` requires `saturating_sub()` instead of `a - b` for `Duration` and `Instant`. Use `(now + CAPTURE_HANG_PAUSE).saturating_sub(Duration::from_millis(1))` here. This repository requirement must be satisfied before merging.
```suggestion
assert!(pause.active_at((now + CAPTURE_HANG_PAUSE).saturating_sub(Duration::from_millis(1))));
```
**Context Used:** AGENTS.md ([source](https://github.com/capsoftware/cap/blob/main/AGENTS.md))
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
Fixed in 7d12f22. The test now uses CAPTURE_HANG_PAUSE.saturating_sub(Duration::from_millis(1)). Instant has no saturating_sub(Duration), so the subtraction happens on the Duration.
| /// Whether a recent hang has paused thumbnail captures; sweeps are not started | ||
| /// while it is. |
There was a problem hiding this comment.
This new comment only restates what captures_paused() does. AGENTS.md bans comments that narrate code behavior and requires non-obvious context instead. Remove these two lines before merging to meet that requirement. Keep the nearby explanation of why hung requests cannot be cancelled.
| /// Whether a recent hang has paused thumbnail captures; sweeps are not started | |
| /// while it is. |
Context Used: AGENTS.md (source)
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop-gpui/src/target_thumbnails.rs
Line: 87-88
Comment:
**Comment repeats the code**
This new comment only restates what `captures_paused()` does. `AGENTS.md` bans comments that narrate code behavior and requires non-obvious context instead. Remove these two lines before merging to meet that requirement. Keep the nearby explanation of why hung requests cannot be cancelled.
```suggestion
```
**Context Used:** AGENTS.md ([source](https://github.com/capsoftware/cap/blob/main/AGENTS.md))
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
A sweep sends its target list before capturing, and the receiver commits that list's signature when the channel closes. A sweep that a hang ended early was therefore recorded as complete, and with an unchanged window list windows_stale() stayed false, so window thumbnails never retried after the pause. Skip the commit while captures are paused so the picker retries the sweep once the pause lifts. Also add the pause duration with Duration::saturating_sub in the test, per the repository's time-subtraction rule.
Refs #2339
When ScreenCaptureKit never answers a thumbnail request, the GPUI app waits on it forever. #2339 shows that this happens in practice: an
SCScreenshotManagerrequest hung right after launch and left the purple screen-recording indicator on.In the GPUI app, that one hang also stopped thumbnails for the rest of the session:
display_inflight(orwindow_inflight) is never cleared, and every laterstart_capturereturns early.Fix (
target_thumbnails.rs)tokio::time::timeout. A healthy 320×180 capture takes milliseconds.start_capturewon't start a sweep while paused, and a running sweep stops before its next target.replayd, so retrying on every 5 s picker poll would only stack more of them.tokio::time::timeoutpanics inside the sweep.Not covered: this only stops Cap from waiting on, and piling up, hung requests. The request that is already stuck stays inside
replayd. The report shows it outlives Cap quitting, so this can't clear a stuck indicator by itself. Doing that would mean moving thumbnails offSCScreenshotManager, for example to a one-frameSCStream, which can be stopped explicitly.Testing
a_hung_capture_times_out_inside_a_sweep_and_pauses_capturesruns a never-resolving future through the realrun_capturepath. It fails if.enable_time()is removed, and it fails if the timeout doesn't start the pause.capture_pause_lasts_for_the_hang_pausechecks the pause covers exactly 5 minutes.cargo test --bin cap-gpui: 1077 passed. rustfmt is clean, and clippy reports nothing in the changed code.Fix the window retry path and satisfy the two repository rules before merging.
Findings
Fix with agent prompt
Summary
This PR adds five-second thumbnail deadlines and pauses new captures for five minutes after a timeout.
Acknowledged by AatmanAJ: A timed-out native request can remain stuck and leave the recording indicator on. The PR explicitly limits this fix to ending Cap’s wait and slowing retries; cancelling the native request is deferred.
Reviews (1) · Last reviewed commit: "fix(desktop-gpui): stop waiting forever ..." · Reviewed by Greptile