Skip to content

fix: stop polling the debug port once the browser has answered - #85

Merged
nathanfallet merged 1 commit into
mainfrom
fix/stop-polling-once-the-browser-answers
Aug 27, 2026
Merged

fix: stop polling the debug port once the browser has answered#85
nathanfallet merged 1 commit into
mainfrom
fix/stop-polling-once-the-browser-answers

Conversation

@nathanfallet

Copy link
Copy Markdown
Member

The bug

The wait loop in DefaultBrowser.start() reads as "try until it connects, up to maxTries times":

delay(config.browserConnectionTimeout)
repeat(config.browserConnectionMaxTries) {
    if (testConnection()) return@repeat
    delay(config.browserConnectionTimeout)
}

return@repeat returns from the lambda, not from the loop — it is a continue, not a break. The loop never stopped early. And because the line it skipped is the delay, a browser that answered on the first try still got every remaining attempt fired at it back to back, with no wait in between.

This is the successful path, not an error path. Every browser start did it.

Standalone reproduction of the loop, run as-is:

testConnection() appelé : 60 fois
delay() exécuté        : 0 fois

So with the defaults, each successful start sends 60 GET /json/version in a burst at a Chrome that has just come up.

The fix

The polling rule moves to awaitConnection(), so it can be tested without a real browser, and uses a genuine early return.

start() also now logs "Connection to browser established" only when the connection actually was established. It used to log it unconditionally — one line above the error saying the browser never opened its port, which is confusing when reading logs of a failed start.

Not changed

The timeouts themselves. 60 tries × 500 ms is still 30 s of budget. It is worth revisiting (zendriver waits 2.5 s, pydoll 10 s), but that is a behaviour change and this is a bug fix — happy to do it in a follow-up.

Tests

AwaitConnectionTest, written red first against a copy of the old loop:

test old loop new
answers immediately → stops polling ❌ 60 attempts, returns false ✅ 1 attempt
answers on the 3rd try → stops there ✅ 3 attempts
never answers → exactly maxTries attempts
waits one interval per failed attempt

The last two passed against the buggy version too — they pin the behaviour that must not change, so the fix cannot trade one bug for another.

Locally: all five targets compile, :core:jvmTest green, detekt findings identical to main (317, same set).

The wait loop in start() read as "try until it connects, up to maxTries times":

    repeat(config.browserConnectionMaxTries) {
        if (testConnection()) return@repeat
        delay(config.browserConnectionTimeout)
    }

`return@repeat` returns from the lambda, not from the loop — it is a `continue`,
not a `break`. So the loop never stopped early, and because the line it skipped
was the `delay`, a browser that answered on the very first try still got all 60
remaining attempts fired at it back to back with no wait in between. That is on
the *successful* path, not an error path: every single browser start did it.

Measured on a standalone reproduction of the loop: 60 calls to testConnection(),
0 delays.

The polling rule moves to awaitConnection() so it can be tested without a real
browser, and start() now logs "Connection to browser established" only when the
connection was actually established — it used to log it unconditionally, one
line above the error saying the browser never opened its port.

No change to the timeouts themselves: 60 tries x 500ms is still 30s of budget.
Worth revisiting separately (zendriver waits 2.5s, pydoll 10s), but that is a
behaviour change and this is a bug fix.
@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
.../kotlin/dev/kdriver/core/browser/DefaultBrowser.kt 66.66% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@nathanfallet
nathanfallet merged commit 8d67555 into main Aug 27, 2026
5 checks passed
@nathanfallet
nathanfallet deleted the fix/stop-polling-once-the-browser-answers branch August 27, 2026 09:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant