Skip to content

Prevent blocking empty fread()#26

Open
divinity76 wants to merge 9 commits into
chrome-php:1.8from
divinity76:patch-5
Open

Prevent blocking empty fread()#26
divinity76 wants to merge 9 commits into
chrome-php:1.8from
divinity76:patch-5

Conversation

@divinity76
Copy link
Copy Markdown

@divinity76 divinity76 commented Mar 16, 2026

There is an issue where this fread can block up to 5 seconds when there is nothing to read.

Fix it by not issuing fread() if stream_select() say there is nothing to read.

Also encountered a strange issue on PHP8.4.12 Ubuntu24.04 where stream_select() would incorrectly return 0 if we had never ran fread() on the socket, so made a workaround to always call fread the first time.

Reproduce script:

<?php

declare(strict_types=1);
require_once(__DIR__ . '/vendor/autoload.php');
$chromeBinary = "/snap/bin/chromium";
$browser_factory = new \HeadlessChromium\BrowserFactory($chromeBinary);
$browser_factory->setOptions([
    "headless" => true,
    "noSandbox" => true,
    'customFlags' => [
        // docker ...
        '--disable-dev-shm-usage',
    ]
]);
$browser = $browser_factory->createBrowser();
$page = $browser->createPage();
$highscore = -INF;
$page->navigate("http://example.com")->waitForNavigation();

for ($i = 0; $i < 100; ++$i) {
$t = microtime(true);
$url = $page->getCurrentUrl();
$t = microtime(true) - $t;
if ($t > $highscore) {
    echo "New highscore: $t seconds for $url\n";
    $highscore = $t;
}
}

output before this patch:

hans@DESKTOP-EE15SLU:~/projects/chrome/hans$ php reproduce.php 
New highscore: 1.0967254638672E-5 seconds for getCurrentUrl() on https://example.com/
New highscore: 0.0005338191986084 seconds for getCurrentUrl() on https://example.com/
New highscore: 0.021073818206787 seconds for getCurrentUrl() on https://example.com/
New highscore: 0.96735405921936 seconds for getCurrentUrl() on https://example.com/
New highscore: 3.1658289432526 seconds for getCurrentUrl() on https://example.com/
New highscore: 5.0055141448975 seconds for getCurrentUrl() on https://example.com/
New highscore: 5.0062091350555 seconds for getCurrentUrl() on https://example.com/
New highscore: 5.0073070526123 seconds for getCurrentUrl() on https://example.com/
New highscore: 5.0073978900909 seconds for getCurrentUrl() on https://example.com/
New highscore: 5.0115480422974 seconds for getCurrentUrl() on https://example.com/
^C

-first took microseconds, then milliseconds, then 3 seconds, then consistently 5 seconds..
(Had to ctrl+c cancel it because it was taking so long...)
Output after this patch:

hans@DESKTOP-EE15SLU:~/projects/chrome/hans$ php reproduce.php 
New highscore: 9.0599060058594E-6 seconds for getCurrentUrl() on https://example.com/
hans@DESKTOP-EE15SLU:~/projects/chrome/hans$ php reproduce.php 
New highscore: 5.9604644775391E-6 seconds for getCurrentUrl() on https://example.com/
hans@DESKTOP-EE15SLU:~/projects/chrome/hans$ php reproduce.php 
New highscore: 1.0967254638672E-5 seconds for getCurrentUrl() on https://example.com/
New highscore: 2.0027160644531E-5 seconds for getCurrentUrl() on https://example.com/
hans@DESKTOP-EE15SLU:~/projects/chrome/hans$ 
  • Consistently execute in microseconds 👍

There is an issue where this fread can block up to 5 seconds.

Fix it by not issuing fread() if stream_select() say there is nothing to read.

Encountered a strange issue on Ubuntu24.04 where stream_select() would incorrectly return 0 if we had never ran fread() on the socket, so made a workaround to always call fread the first time, even if socket_select() say there is nothing to read.


- resolves chrome-php/chrome#711
- resolves chrome-php/chrome#646
- resolves chrome-php/chrome#704

- probably resolves chrome-php/chrome#710
@divinity76 divinity76 changed the title Prevent blocking fread() Prevent blocking empty fread() Mar 16, 2026
@nevez
Copy link
Copy Markdown

nevez commented May 16, 2026

Any news about this pull request? Without it chrome-php is unnecessarily slow...

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

Labels

None yet

2 participants