Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions openadapt_capture/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,14 +747,14 @@ def _start(self) -> subprocess.Popen[bytes]:
)
try:
self._input_thread.start()
except BaseException:
except BaseException as exc:
process.kill()
process.wait()
stderr_file.close()
self._process = None
self._stderr_file = None
self._input_thread = None
raise
raise FFmpegEncodingError(f"Could not start FFmpeg input worker: {exc}") from exc
return process

def _stderr_detail(self) -> str:
Expand Down
27 changes: 27 additions & 0 deletions tests/test_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,33 @@ def test_direct_encode_retries_partial_pipe_writes(tmp_path, monkeypatch):
assert video._read_timing_box(output) == (Fraction(24), [(0, 0.0)])


def test_direct_encode_worker_start_failure_reaps_process(tmp_path, monkeypatch):
executable = tmp_path / "ffmpeg"
executable.write_bytes(b"fake")
stage = video.FFmpegFrameStage(
tmp_path / "capture.mp4",
_small_stream(),
_provision(executable),
)
process = _FakeProcess(stage._encode_command())
_install_fake_popen(monkeypatch, process)

def fail_start(_thread):
raise RuntimeError("thread resources unavailable")

monkeypatch.setattr(video.threading.Thread, "start", fail_start)

with pytest.raises(
video.FFmpegEncodingError,
match="Could not start FFmpeg input worker",
):
stage.stage_frame(Image.new("RGB", (2, 1), "red"), 0)
assert process._killed is True
assert process.returncode == -9
assert stage._process is None
assert stage._input_thread is None


def test_direct_encode_zero_length_pipe_write_fails_loudly(tmp_path, monkeypatch):
executable = tmp_path / "ffmpeg"
executable.write_bytes(b"fake")
Expand Down
Loading