mirror of
https://github.com/daijro/camoufox.git
synced 2026-09-06 08:00:36 +00:00
Fix playwright session leak when launch or close raises (#82)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
3911d11dbd
commit
0d5440117b
@@ -32,13 +32,24 @@ class AsyncCamoufox(PlaywrightContextManager):
|
||||
|
||||
async def __aenter__(self) -> Union[Browser, BrowserContext]:
|
||||
_playwright = await super().__aenter__()
|
||||
self.browser = await AsyncNewBrowser(_playwright, **self.launch_options)
|
||||
try:
|
||||
self.browser = await AsyncNewBrowser(_playwright, **self.launch_options)
|
||||
except BaseException as e:
|
||||
# Any launch failure (InvalidProxy, missing browser, bad options, ...)
|
||||
# must tear down the playwright session started above so the driver
|
||||
# process/connection is not leaked.
|
||||
await super().__aexit__(type(e), e, e.__traceback__)
|
||||
raise
|
||||
return self.browser
|
||||
|
||||
async def __aexit__(self, *args: Any):
|
||||
if self.browser:
|
||||
await self.browser.close()
|
||||
await super().__aexit__(*args)
|
||||
# Run the base teardown even if browser.close() raises (e.g. the browser
|
||||
# process already crashed), so the playwright driver/connection is not leaked.
|
||||
try:
|
||||
if self.browser:
|
||||
await self.browser.close()
|
||||
finally:
|
||||
await super().__aexit__(*args)
|
||||
|
||||
|
||||
@overload
|
||||
|
||||
@@ -13,7 +13,6 @@ from typing_extensions import Literal
|
||||
|
||||
from camoufox.virtdisplay import VirtualDisplay
|
||||
|
||||
from .exceptions import InvalidProxy
|
||||
from .fingerprints import generate_context_fingerprint
|
||||
from .utils import launch_options, sync_attach_vd
|
||||
|
||||
@@ -33,15 +32,26 @@ class Camoufox(PlaywrightContextManager):
|
||||
super().__enter__()
|
||||
try:
|
||||
self.browser = NewBrowser(self._playwright, **self.launch_options)
|
||||
except InvalidProxy as e:
|
||||
super().__exit__(InvalidProxy, e, None)
|
||||
except BaseException as e:
|
||||
# Any launch failure (InvalidProxy, missing browser, bad options, ...)
|
||||
# must tear down the playwright session started above. Leaking it leaves
|
||||
# the sync API's event loop in a "running" state, so every later sync
|
||||
# Camoufox/Playwright start in this thread fails with "Sync API inside
|
||||
# the asyncio loop" until the process restarts (#82).
|
||||
super().__exit__(type(e), e, e.__traceback__)
|
||||
raise
|
||||
return self.browser
|
||||
|
||||
def __exit__(self, *args: Any):
|
||||
if self.browser:
|
||||
self.browser.close()
|
||||
super().__exit__(*args)
|
||||
# Run the base teardown even if browser.close() raises (e.g. the browser
|
||||
# process already crashed). Skipping it leaks the sync API's event loop in a
|
||||
# "running" state, so every later sync Camoufox/Playwright start in the same
|
||||
# thread fails with "Sync API inside the asyncio loop" until process restart.
|
||||
try:
|
||||
if self.browser:
|
||||
self.browser.close()
|
||||
finally:
|
||||
super().__exit__(*args)
|
||||
|
||||
|
||||
@overload
|
||||
|
||||
Reference in New Issue
Block a user