Skip to content

Commit

Permalink
exif: improve stream handling (#1283)
Browse files Browse the repository at this point in the history
Signed-off-by: Varun Patil <radialapps@gmail.com>
  • Loading branch information
pulsejet committed Oct 13, 2024
1 parent 2bec243 commit a4b8960
Showing 1 changed file with 33 additions and 17 deletions.
50 changes: 33 additions & 17 deletions lib/Exif.php
Original file line number Diff line number Diff line change
Expand Up @@ -449,25 +449,37 @@ private static function initializeStaticExiftoolProc(): void
*/
private static function readOrTimeout($handle, int $timeout, ?string $delimiter = null): string
{
$buf = '';
$waitedMs = 0;
$buffer = '';

while ($waitedMs < $timeout && ($delimiter ? !str_ends_with($buf, $delimiter) : !feof($handle))) {
$r = stream_get_contents($handle);
if (empty($r)) {
++$waitedMs;
usleep(1000);
// Absolute time to wait until
$timeEnd = microtime(true) + $timeout / 1000;

// Select expects variables
$read = [$handle];
$write = $except = null;

while (microtime(true) < $timeEnd) {
// Check if we have delimiter or eof
if (feof($handle) || ($delimiter && str_ends_with($buffer, $delimiter))) {
return $buffer;
}

// Wait for data to read
$ready = stream_select($read, $write, $except, 1, 0);
if (false === $ready) {
throw new \Exception('Stream select error');
}

// No data is available yet
if (0 === $ready) {
continue;
}
$buf .= $r;
}

if ($waitedMs >= $timeout) {
throw new \Exception('Timeout');
// Append to buffer
$buffer .= stream_get_contents($handle);
}

return $buf;
throw new \Exception('Timeout');
}

private static function getExifFromLocalPathWithStaticProc(string $path): array
Expand Down Expand Up @@ -518,26 +530,30 @@ private static function getExifFromLocalPathWithSeparateProc(string $path, array

try {
$stdout = self::readOrTimeout($pipes[1], self::EXIFTOOL_TIMEOUT);

return self::processStdout($stdout);
} catch (\Exception $ex) {
error_log("Exiftool timeout: [{$path}]");
error_log("Timeout reading from exiftool: [{$path}]");

throw new \Exception('Could not read from Exiftool');
throw $ex;
} finally {
fclose($pipes[1]);
fclose($pipes[2]);
proc_terminate($proc);
proc_close($proc);
}

return self::processStdout($stdout);
}

/** Get json array from stdout of exiftool */
private static function processStdout(string $stdout): array
{
$json = json_decode($stdout, true);
if (!$json) {
throw new \Exception('Could not read exif data');
throw new \Exception('Failed to parse exiftool output as JSON');
}

if (!\is_array($json) || !\count($json)) {
throw new \Exception('Exiftool output is not an array with at least one element');
}

return $json[0];
Expand Down

0 comments on commit a4b8960

Please sign in to comment.