Skip to content

Commit 6f182b0

Browse files
committed
Add fix. TODO: Figure out test
1 parent f2e1b6f commit 6f182b0

File tree

1 file changed

+16
-16
lines changed

1 file changed

+16
-16
lines changed

src/crawlee/browsers/_playwright_browser_controller.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -80,24 +80,30 @@ def __init__(
8080

8181
self._context_creation_lock: Lock | None = None
8282

83-
8483
async def _get_context_creation_lock(self) -> Lock:
85-
"""Context checking and creation should be done with lock to prevent multiple attempts to create context."""
84+
"""Get context checking and creation lock.
85+
86+
It should be done with lock to prevent multiple concurrent attempts to create context, which could lead to
87+
memory leak as one of the two concurrently created contexts will become orphaned and not properly closed.
88+
"""
8689
if self._context_creation_lock:
8790
return self._context_creation_lock
88-
self._context_creation_lock= Lock()
91+
self._context_creation_lock = Lock()
8992
return self._context_creation_lock
9093

91-
async def _ensure_browser_context(self,
92-
browser_new_context_options: Mapping[str, Any] | None = None,
93-
proxy_info: ProxyInfo | None = None,
94-
) -> None:
94+
async def _get_browser_context(
95+
self,
96+
browser_new_context_options: Mapping[str, Any] | None = None,
97+
proxy_info: ProxyInfo | None = None,
98+
) -> BrowserContext:
99+
"""Ensure that the browser context is set."""
95100
async with await self._get_context_creation_lock():
96101
if not self._browser_context:
97102
self._browser_context = await self._create_browser_context(
98103
browser_new_context_options=browser_new_context_options,
99104
proxy_info=proxy_info,
100105
)
106+
return self._browser_context
101107

102108
@property
103109
@override
@@ -170,8 +176,8 @@ async def new_page(
170176
)
171177
page = await new_context.new_page()
172178
else:
173-
await self._ensure_browser_context()
174-
page = await self._browser_context.new_page()
179+
_browser_context = await self._get_browser_context()
180+
page = await _browser_context.new_page()
175181

176182
# Handle page close event
177183
page.on(event='close', f=self._on_page_close)
@@ -181,7 +187,6 @@ async def new_page(
181187
self._last_page_opened_at = datetime.now(timezone.utc)
182188

183189
self._total_opened_pages += 1
184-
185190
return page
186191

187192
@override
@@ -217,7 +222,6 @@ async def _create_browser_context(
217222
Create context without headers and without fingerprints if neither `self._header_generator` nor
218223
`self._fingerprint_generator` is available.
219224
"""
220-
start = datetime.now(timezone.utc)
221225
browser_new_context_options = dict(browser_new_context_options) if browser_new_context_options else {}
222226
if proxy_info:
223227
if browser_new_context_options.get('proxy'):
@@ -230,14 +234,11 @@ async def _create_browser_context(
230234
)
231235

232236
if self._fingerprint_generator:
233-
234-
c = await AsyncNewContext(
237+
return await AsyncNewContext(
235238
browser=self._browser,
236239
fingerprint=self._fingerprint_generator.generate(),
237240
**browser_new_context_options,
238241
)
239-
logger.warning(f"Fingerprint generation time [s]: {(datetime.now(timezone.utc) - start).total_seconds()}")
240-
return c
241242

242243
if self._header_generator:
243244
extra_http_headers = dict(
@@ -259,5 +260,4 @@ async def _create_browser_context(
259260
browser_new_context_options['extra_http_headers'] = browser_new_context_options.get(
260261
'extra_http_headers', extra_http_headers
261262
)
262-
logger.warning(f"Fingerprint generation time [s]: {(datetime.now(timezone.utc)-start).total_seconds()}")
263263
return await self._browser.new_context(**browser_new_context_options)

0 commit comments

Comments
 (0)