Skip to content

Commit

Permalink
Attempt to forcibly close & restart browser if it hangs
Browse files Browse the repository at this point in the history
Sometimes the browser is running and answering on the websocket
but never seems to actually handle a Page.navigate. Attempt
to detect this by forcing a visit to about:blank at the start
of every scenario. If that fails then stop the driver (which
closes the Chrome tab) and restart it (which opens a new tab)
- hopefully that will help?
  • Loading branch information
acoulton committed Sep 15, 2022
1 parent 9763728 commit 1d1454d
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 5 deletions.
38 changes: 37 additions & 1 deletion src/ChromeDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ public function ensureStarted()
*/
public function stop()
{
// SEE ALSO implementation of forcePageResetOrRestartDriver
$this->ensureStarted();
try {
$this->reset();
Expand Down Expand Up @@ -171,12 +172,19 @@ public function stop()
*/
public function reset()
{
// Sometimes Chrome gets into a bonkers state where the page seems to hang and even Page.navigate doesn't return
// a response until the next time you call Page.navigate, at which time we get a net::ERR_ABORTED for the
// previous for no apparent reason. That will then continue to happen for *every* Page.navigate command for the
// rest of the run - even though the socket is quite happy and still accepts and responds to the
// Network.clearBrowserCookies.
try {
$this->ensureStarted();
$this->document = 'document';
$this->deleteAllCookies();
$this->connectToWindow($this->main_window);
$this->page->reset();

$this->forcePageResetOrRestartDriver();

if ($this->request_headers !== []) {
$this->request_headers = [];
$this->sendRequestHeaders();
Expand All @@ -191,6 +199,34 @@ public function reset()
}
}

private function forcePageResetOrRestartDriver()
{
try {
$this->page->reset();
return;
} catch (DriverException $e) {
\fwrite(
STDOUT,
sprintf(
"ERROR: Failed to reset page [%s] %s - stopping & restarting",
\get_class($e),
$e->getMessage()
)
);
ChromeDriverDebugLogger::instance()->logDriverException($e, 'When resetting to about:blank');
}

// If we got here then visiting about:blank failed
$this->page->close();
$this->http_client->get($this->api_url.'/json/close/'.$this->current_window);
$this->browser->close();
$this->is_started = FALSE;

// And now restart
$this->start();
$this->connectToWindow($this->main_window);
}

/**
* Visit specified URL.
*
Expand Down
7 changes: 5 additions & 2 deletions src/ChromePage.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,15 @@ public function reset()
{
$this->response = null;
$this->javascript_dialog_handler = null;
$this->visit('about:blank', new \DateTimeImmutable('+5 seconds'));
}

public function visit($url)
public function visit($url, ?\DateTimeImmutable $timeout = NULL)
{
$this->setPageReady(FALSE, __METHOD__);
$this->send('Page.navigate', ['url' => $url]);
// Page.navigate does not return until after the initial network request so it needs to be able to run for at least as
// long as you expect that to take.
$this->send('Page.navigate', ['url' => $url], $timeout ?? new \DateTimeImmutable('+30 seconds'));
}

public function reload()
Expand Down
7 changes: 5 additions & 2 deletions src/DevToolsConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public function close()
* @return null|string|string[][]
* @throws \Exception
*/
public function send($command, array $parameters = [])
public function send($command, array $parameters = [], ?\DateTimeImmutable $timeout = NULL)
{
$payload['id'] = $this->command_id++;
$payload['method'] = $command;
Expand All @@ -76,7 +76,10 @@ public function send($command, array $parameters = [])

$data = $this->waitFor(function ($data) use ($payload) {
return array_key_exists('id', $data) && $data['id'] == $payload['id'];
}, 'send-'.$payload['id']);
},
'send-'.$payload['id'],
$timeout
);

if (isset($data['result'])) {
return $data['result'];
Expand Down

0 comments on commit 1d1454d

Please sign in to comment.