security-union / security-union/remote-shutter

Video recording failures hang both devices instead of erroring

Open
#158 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Swift
Stars
19
Forks
3
Avg merge
28m
Merged PRs (30d)
6

Description

Found while fixing the Mac-as-camera recording hang (PR #157). That bug's root cause is fixed, but the three things that turned a settings rejection into a permanent two-device freeze are all still present. The next stop-side failure — from any cause — will hang exactly the same way.

Three silent-failure amplifiers, in the order they bite:

1. configureAudioForRecording reports success when it failed

RemoteCam/CaptureEngine.swift:213-219

if captureSession.canAddInput(audioDeviceInput) {
    captureSession.addInput(audioDeviceInput)
} else {
    print("Could not add audio device input to the session")   // ← prints, then falls through
}
if captureSession.canAddOutput(audioDataOutput) { ... }        // ← no else at all
...
return true                                                     // ← unconditional

RecordingPipeline.swift:107's guard self.configureAudio(...) therefore passes, and the deliberate MicrophoneAccessDenied bail-out at :107-114 never fires. Fix: return false when the input or the output can't be added. That alone routes it to the already-wired clean failure (error ack + "Unable to record audio" alert).

2. stopRecording silently drops the whole protocol

RemoteCam/RecordingPipeline.swift:147

if self.recordingWillBeStopped || !self.isRecordingStorage {
    return          // no finishWriting, no StopRecordingVideoResp, no error, no log
}

The guard conflates two different states. Split them:

  • recordingWillBeStopped → a stop is in flight, ignore (correct today).
  • !isRecordingStorage with recordingWillBeStarted == true → the start never completed. Tear down the pending writer, clear recordingWillBeStarted (today it stays true forever, poisoning every future startRecording via the guard at :97), and emit StopRecordingVideoResp(error:) so the monitor unblocks.

Also guard the assetWriter? optional-chain at :157: a nil writer means the completion never runs and recordingWillBeStopped stays true forever — the same permanent poison. Never call finishWriting on a .unknown-status writer (it throws).

3. .monitorWaitingForVideo is the only monitor wait state with no timeout

RemoteCam/SessionCoordinator.swift:1540

Every other wait state arms a scheduleTimeout (:1187, :1200, :1209, :1229, :1258, :1507), and the watch path recovers from the identical underlying no-op via :1739/:1753. The multipeer path is the outlier.

⚠️ A flat 10s would break large transfers, which legitimately take minutes. Needs to be transfer-aware: arm until the transfer starts, then rely on progress.

Why it matters

Any one of these alone is survivable. Together they convert any recording-side failure into both devices hanging forever with no error and no log. Worth fixing as one PR.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the named paths in RemoteCam/CaptureEngine.swift, RecordingPipeline.swift, and SessionCoordinator.swift, especially the cited line ranges and the existing timeout and watch recovery paths. Trace the recording start/stop protocol and failure acknowledgements before changing behavior. Done means every cited failure unblocks both devices, clears poisoned recording state, reports an error, and uses a transfer-aware timeout without interrupting large transfers.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, swift
Domain
audio-video-rtc, mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
63/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.