Skip to content

Quickly re-opening tabs could hang some (cookies, set_all?) CDP connections #82

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
JabLuszko opened this issue Feb 25, 2025 · 1 comment

Comments

@JabLuszko
Copy link

JabLuszko commented Feb 25, 2025

This is kinda stupid, but hit that somewhere. If you re-open tabs too fast the CDP/Connection doesn't get updated on time and when using cookies.set_all() it's trying to update [I think] previous, closed tab and everything hangs up.

import asyncio
import zendriver as zd

async def main():
    
    browser = await zd.start()
    _page = await browser.get("https://httpbin.org/cookies/set?foo=bar&bar=foo&test=test&test2=test2&test3=test3")
    cookies = await browser.cookies.get_all()
    #print(cookies)
      
    tab = None
    for i in range(0, 100):
        print(f"(Re-)Opening tab {i}")
        if not tab:
            tab = await browser.get("about:blank")
        else:
            new_tab = await tab.get("about:blank", new_tab=True)
            await tab.close()
            tab = new_tab
        #await tab.sleep(0.1)
        await browser.cookies.set_all(cookies)

if __name__ == "__main__":
    asyncio.run(main())

Uncommenting tab.sleep() or enabling too many debug logs slows things down and it's not reproducible anymore.
Added single debug log to Browser set_all to see what the Connection looks like and I can see that when it hangs up it's the same tab ID/number that was in previous run and the page is blank.

When going (too) fast

(Re-)Opening tab 0
got answer for <Transaction
        method: Page.navigate
        status: pending
        success: True> (message_id:0)
got answer for <Transaction
        method: Target.getTargetInfo
        status: pending
        success: True> (message_id:0)
set_all cookies: connection found <Tab [A96AFD4FEAFF49B2B4E574EBA47FA63E] [page] >
got answer for <Transaction
        method: Storage.setCookies
        status: pending
        success: True> (message_id:0)
(Re-)Opening tab 1
got answer for <Transaction
        method: Target.createTarget
        status: pending
        success: True> (message_id:8)
got answer for <Transaction
        method: Target.getTargetInfo
        status: pending
        success: True> (message_id:0)
got answer for <Transaction
        method: Target.closeTarget
        status: pending
        success: True> (message_id:0)
set_all cookies: connection found <Tab [A96AFD4FEAFF49B2B4E574EBA47FA63E] [page] >
connection listener exception while reading websocket:
no close frame received or sent
task was cancelled while reading websocket, breaking loop
task was cancelled while reading websocket, breaking loop

❌ closed websocket connection to ws://127.0.0.1:56769/devtools/browser/ed746fc7-8be0-48a7-8b89-c301c2e537b7
Traceback (most recent call last):
  File "C:\Program Files\Python313\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "C:\Program Files\Python313\Lib\asyncio\base_events.py", line 725, in run_until_complete
    return future.result()
           ~~~~~~~~~~~~~^^
  File "C:\Users\a\wtf.py", line 26, in main
    await browser.cookies.set_all(cookies)
  File "C:\Users\a\venv\Lib\site-packages\zendriver\core\browser.py", line 711, in set_all
    await connection.send(cdp.storage.set_cookies(cookies))
  File "C:\Users\a\venv\Lib\site-packages\zendriver\core\connection.py", line 477, in send
    return await tx
           ^^^^^^^^
asyncio.exceptions.CancelledError

When going slower

set_all cookies: connection found <Tab [1812E7574F4EA3FF873E1999B76B4515] [page] [url: about:blank]>
got answer for <Transaction
        method: Storage.setCookies
        status: pending
        success: True> (message_id:0)
(Re-)Opening tab 1
got answer for <Transaction
        method: Target.createTarget
        status: pending
        success: True> (message_id:9)
got answer for <Transaction
        method: Target.getTargetInfo
        status: pending
        success: True> (message_id:0)
got answer for <Transaction
        method: Target.closeTarget
        status: pending
        success: True> (message_id:0)
got answer for <Transaction
        method: Target.getTargetInfo
        status: pending
        success: True> (message_id:0)
connection listener exception while reading websocket:
no close frame received or sent
set_all cookies: connection found <Tab [B277803FE4750D8416CEC6D72FE41E67] [page] [url: about:blank]>
got answer for <Transaction
        method: Storage.setCookies
        status: pending
        success: True> (message_id:0)
(Re-)Opening tab 2
got answer for <Transaction
        method: Target.createTarget
        status: pending
        success: True> (message_id:15)
got answer for <Transaction
        method: Target.getTargetInfo
        status: pending
        success: True> (message_id:0)
got answer for <Transaction
        method: Target.closeTarget
        status: pending
        success: True> (message_id:0)
connection listener exception while reading websocket:
no close frame received or sent
got answer for <Transaction
        method: Target.getTargetInfo
        status: pending
        success: True> (message_id:0)
set_all cookies: connection found <Tab [2DD6860E2A8D2F0562B719CCC73B5A1B] [page] [url: about:blank]>

Same thing happening in latest (yeah :D) nodriver so it's kinda old(er) issue.

@ccev
Copy link
Contributor

ccev commented Mar 3, 2025

Zendriver doesn't properly wait for target updates. They're handled in the background in Browser._handle_target_update.

Browser.new (which is called by Tab.get in the example code) waits 0.25s before returning, I believe this is the original author's way to wait for chrome to return the target update events. Tab.close, however, doesn't have this sleep, which makes the function return without waiting the TargetDestroyed and TargetInfoChanged events to be returned by chrome.

I've opened #90 with what I've found.

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

No branches or pull requests

2 participants