Skip to content

fix: fix process handling bugs #966

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
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion playwright/async_api/_context_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ async def __aenter__(self) -> AsyncPlaywright:
loop.create_task(self._connection.run())
playwright_future = self._connection.playwright_future

done, pending = await asyncio.wait(
done, _ = await asyncio.wait(
{self._connection._transport.on_error_future, playwright_future},
return_when=asyncio.FIRST_COMPLETED,
)
Expand Down
27 changes: 18 additions & 9 deletions playwright/sync_api/_context_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.

import asyncio
import sys
from typing import Any

from greenlet import greenlet
Expand All @@ -32,15 +33,15 @@
class PlaywrightContextManager:
def __init__(self) -> None:
self._playwright: SyncPlaywright
self._loop: asyncio.AbstractEventLoop
self._own_loop = False

def __enter__(self) -> SyncPlaywright:
loop: asyncio.AbstractEventLoop
own_loop = None
try:
loop = asyncio.get_running_loop()
self._loop = loop = asyncio.get_running_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
own_loop = loop
self._loop = loop = asyncio.new_event_loop()
self._own_loop = True
if loop.is_running():
raise Error(
"""It looks like you are using Playwright Sync API inside the asyncio loop.
Expand All @@ -50,10 +51,6 @@ def __enter__(self) -> SyncPlaywright:
def greenlet_main() -> None:
loop.run_until_complete(self._connection.run_as_sync())

if own_loop:
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()

global dispatcher_fiber
dispatcher_fiber = greenlet(greenlet_main)
self._connection = Connection(
Expand Down Expand Up @@ -81,3 +78,15 @@ def start(self) -> SyncPlaywright:

def __exit__(self, *args: Any) -> None:
self._connection.stop_sync()
# In Python 3.7, self._connection._transport.wait_until_stopped() hangs because
# it does not uses ThreadedChildWatcher which is used in Python 3.8+.
# Hence waiting for child process is skipped in Python 3.7.
# See https://bugs.python.org/issue35621
# See https://stackoverflow.com/questions/28915607/does-asyncio-support-running-a-subprocess-from-a-non-main-thread/28917653#28917653
if sys.version_info >= (3, 8):
self._loop.run_until_complete(
self._connection._transport.wait_until_stopped()
)
if self._own_loop:
self._loop.run_until_complete(self._loop.shutdown_asyncgens())
self._loop.close()