Skip to content

[BUG] Task exception was never retrieved when continue_ race with page closed event #1165

Closed
@x0day

Description

@x0day

Context:

  • Playwright Version: 1.19.0
  • Operating System: Mac
  • Python version: 3.9
  • Browser: Chromium

Code Snippet

import asyncio
import logging

from playwright.async_api import async_playwright, Route, Error as PlaywrightApiError


async def on_request(route: Route):
    # simulate some time-consuming operations
    await asyncio.sleep(0.5)
    await route.continue_()


async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch()

        for _ in range(2):
            page = await browser.new_page()
            page.set_default_timeout(500)
            await page.route("**/*", on_request)
            try:
                await page.goto("https://playwright.dev")
            except PlaywrightApiError as exc:
                logging.error(f"exc: {exc}")
            finally:
                await page.close()

        await asyncio.sleep(1)

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    asyncio.run(main(), debug=True)

OUTPUT:

...
ERROR:asyncio:Task exception was never retrieved
future: <Task finished name='Task-8' coro=<Channel.send() done, defined at /Users/x/PycharmProjects/playwright-python/playwright/_impl/_connection.py:38> exception=Error('Target page, context or browser has been closed') created at /usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/tasks.py:361>
source_traceback: Object created at (most recent call last):
  File "/Users/x/Library/Application Support/JetBrains/PyCharmCE2021.3/scratches/scratch.py", line 32, in <module>
    asyncio.run(main(), debug=True)
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 629, in run_until_complete
    self.run_forever()
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 596, in run_forever
    self._run_once()
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 1882, in _run_once
    handle._run()
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "/Users/x/Library/Application Support/JetBrains/PyCharmCE2021.3/scratches/scratch.py", line 10, in on_request
    await route.continue_()
  File "/Users/x/PycharmProjects/playwright-python/playwright/async_api/_generated.py", line 762, in continue_
    await self._async(
  File "/Users/x/PycharmProjects/playwright-python/playwright/_impl/_network.py", line 269, in continue_
    await self._race_with_page_close(
  File "/Users/x/PycharmProjects/playwright-python/playwright/_impl/_network.py", line 289, in _race_with_page_close
    [asyncio.create_task(future), page._closed_or_crashed_future],
  File "/usr/local/Cellar/[email protected]/3.9.9/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/tasks.py", line 361, in create_task
    task = loop.create_task(coro)
Traceback (most recent call last):
  File "/Users/x/PycharmProjects/playwright-python/playwright/_impl/_connection.py", line 39, in send
    return await self.inner_send(method, params, False)
  File "/Users/x/PycharmProjects/playwright-python/playwright/_impl/_connection.py", line 63, in inner_send
    result = next(iter(done)).result()
playwright._impl._api_types.Error: Target page, context or browser has been closed
INFO:asyncio:<_UnixReadPipeTransport fd=8 polling> was closed by peer
DEBUG:asyncio:process 98057 exited with returncode 0
INFO:asyncio:<_UnixSubprocessTransport pid=98057 running stdin=<_UnixWritePipeTransport closed fd=7 closed> stdout=<_UnixReadPipeTransport closed fd=8 closed>> exited with return code 0
DEBUG:asyncio:Close <_UnixSelectorEventLoop running=False closed=False debug=True>
...

Describe the bug

with a long-running browser, after page created, hook the route of page. and do some operation long than timeout, and will see some error log print.
maybe bug is at here. fut task is created but without any exception handler.

async def _race_with_page_close(self, future: Coroutine) -> None:
if hasattr(self.request.frame, "_page"):
page = self.request.frame._page
# When page closes or crashes, we catch any potential rejects from this Route.
# Note that page could be missing when routing popup's initial request that
# does not have a Page initialized just yet.
await asyncio.wait(
[asyncio.create_task(future), page._closed_or_crashed_future],
return_when=asyncio.FIRST_COMPLETED,
)

POC to fix

    async def _race_with_page_close(self, future: Coroutine) -> None:
        if hasattr(self.request.frame, "_page"):
            page = self.request.frame._page
            # When page closes or crashes, we catch any potential rejects from this Route.
            # Note that page could be missing when routing popup's initial request that
            # does not have a Page initialized just yet.
            fut = asyncio.create_task(future)
            await asyncio.wait(
                [fut, page._closed_or_crashed_future],
                return_when=asyncio.FIRST_COMPLETED,
            )
            if page._closed_or_crashed_future.done():
                await asyncio.gather(fut, return_exceptions=True)
        else:
            await future

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions