Skip to content

fix(previews): ffprobe hangs#60916

Open
adduxa wants to merge 1 commit into
nextcloud:masterfrom
adduxa:fix/previews/ffprobe-hangs
Open

fix(previews): ffprobe hangs#60916
adduxa wants to merge 1 commit into
nextcloud:masterfrom
adduxa:fix/previews/ffprobe-hangs

Conversation

@adduxa
Copy link
Copy Markdown
Contributor

@adduxa adduxa commented Jun 1, 2026

Summary

Fix pipe buffer deadlock in useHdr() in lib/private/Preview/Movie.php.

When ffprobe produces more than ~64KB on stderr, the sequential stream_get_contents calls
deadlock: PHP blocks reading stdout while ffprobe blocks flushing stderr. This caused
occ preview:generate-all to hang indefinitely on certain video files.

A tempting workaround is to swap the two stream_get_contents calls (reading stderr first),
but I'm not sure if ffprobe is guaranteed to produce <64KB on the stdout for this call.

Fix drains both pipes concurrently using stream_select with non-blocking I/O.

TODO

  • ...

Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

Signed-off-by: Andrey Dyakov <adduxa@gmail.com>
@adduxa adduxa requested a review from a team as a code owner June 1, 2026 21:27
@adduxa adduxa requested review from ArtificialOwl, artonge, icewind1991 and leftybournes and removed request for a team June 1, 2026 21:27
@susnux susnux added bug 3. to review Waiting for reviews labels Jun 1, 2026
@susnux susnux added this to the Nextcloud 35 milestone Jun 1, 2026
}
foreach ($read as $pipe) {
$chunk = fread($pipe, 8192);
if ($chunk === false) continue;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Will fail CI lint.

!feof($test_hdr_pipes[2]) ? $test_hdr_pipes[2] : null,
]);
$write = $except = [];
if (stream_select($read, $write, $except, 5) === false) {
Copy link
Copy Markdown
Member

@solracsf solracsf Jun 2, 2026

Choose a reason for hiding this comment

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

This 5 is a per-iteration timeout. Only the false (error) return is handled; the 0 (timeout) return falls through, $read becomes empty, the foreach does nothing, and the while loops again. So if ffprobe truly hangs (produces no output and never closes its pipes), this spins every 5s forever: the same "hangs indefinitely" symptom the PR title targets, just via a different path.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks! I will search for the solution.

Do you know if stdout is always <64k here? Is it acceptable to just read stderr first in this case?

This approach is used at https://github.com/adduxa/server/blob/1bcc80b5f45a0d8619df64edbd2fec797fd70cd9/lib/private/Preview/Movie.php#L374 for ffmpeg

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

Labels

3. to review Waiting for reviews bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: preview:generate-all hangs indefinitely on a specific .MTS video file waiting for ffprobe

3 participants