Skip to content

fix(capture): honor cancellation during ScreenCaptureKit retry sleeps#290

Closed
SebTardif wants to merge 2 commits into
openclaw:mainfrom
SebTardif:fix/screencapture-retry-honor-cancel-289
Closed

fix(capture): honor cancellation during ScreenCaptureKit retry sleeps#290
SebTardif wants to merge 2 commits into
openclaw:mainfrom
SebTardif:fix/screencapture-retry-honor-cancel-289

Conversation

@SebTardif

Copy link
Copy Markdown
Contributor

What Problem This Solves

After a transient ScreenCaptureKit denial, three retry paths sleep with try? await Task.sleep before a second attempt:

  1. ScreenCaptureFallbackRunner.run
  2. ScreenCaptureFallbackRunner.runCapture
  3. ScreenRecordingPermissionChecker.hasPermission

try? swallows CancellationError, so a canceled capture or permission check can still run a full second ScreenCaptureKit attempt after the ~350ms delay.

Closes #289

Evidence

Same cancel-swallow class as merged #270 / #271 / #267 / #230. Introduced with concurrent live-area capture stabilization in 6b2554a (2026-05-07).

Prior closed attempts (code was right; merge blocked on live SCK proof):

Changes

  • Use try await Task.sleep on all three transient-denial retry sleeps so cancellation aborts before the second SCK call
  • Unit tests for permission probe and fallback runner cancel-during-sleep
  • Live proof harness: scripts/prove-live-sck-cancel.sh (production ScreenCaptureFallbackRunner + real SCStreamErrorDomain)

Real behavior proof

Command: bash scripts/prove-live-sck-cancel.sh

Environment: macOS arm64, Screen Recording available for host process; proof binary ad-hoc signed (Command Line Tools)

Before (unfixed / control path): non-canceled transient denial path performs 2 real SCStream start attempts (control attempts=2)

After (fixed / cancel path): cancel ~50ms into 350ms denial sleep yields 1 real SCStream start attempt and CancellationError (cancel attempts=1, no second SCK call)

Unit tests:

swift test --package-path Core/PeekabooAutomationKit --filter ScreenRecordingPermissionCancel
swift test --package-path Core/PeekabooCore --filter ScreenCaptureFallbackRunner

(all pass)

Live transcript (this host):

live seed error: domain=com.apple.ScreenCaptureKit.SCStreamErrorDomain code=-3812
PASS control: non-canceled path retried once (2 real SCK calls)
PASS cancel: canceled during denial sleep with no second real SCK call
ALL LIVE CHECKS PASSED

Related

@clawsweeper

clawsweeper Bot commented Jul 22, 2026

Copy link
Copy Markdown

ClawSweeper status: review started.

I am starting a fresh review of this pull request: fix(capture): honor cancellation during ScreenCaptureKit retry sleeps This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

@SebTardif

Copy link
Copy Markdown
Contributor Author

Closing this PR. The fix for #289 landed through steipete's commit 7516d88 in v3.9.7, which addresses all three ScreenCaptureKit retry sites with the same try await Task.sleep + try Task.checkCancellation() approach. Thanks for shipping it!

@SebTardif SebTardif closed this Jul 22, 2026
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.

ScreenCaptureKit transient-denial retry swallows cancellation (second attempt after cancel)

1 participant