prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Async API - asyncio error
  After updating to the 1.9.2 version, for **Async API** I get the following error:
  
  Exception ignored in: <function BaseSubprocessTransport.__del__ at 0x0000000002E1E9D0>
  Traceback (most recent call last):
    File "C:\Users\Matthew\AppData\Local\Programs\Python\Python39\lib\asyncio\base_subprocess.py", line 126, in __del__
      self.close()
    File "C:\Users\Matthew\AppData\Local\Programs\Python\Python39\lib\asyncio\base_subprocess.py", line 104, in close  
      proto.pipe.close()
    File "C:\Users\Matthew\AppData\Local\Programs\Python\Python39\lib\asyncio\proactor_events.py", line 108, in close  
      self._loop.call_soon(self._call_connection_lost, None)
    File "C:\Users\Matthew\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 746, in call_soon
      self._check_closed()
    File "C:\Users\Matthew\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 510, in _check_closed
      raise RuntimeError('Event loop is closed')
  RuntimeError: Event loop is closed
  Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000000002E4A280>
  Traceback (most recent call last):
    File "C:\Users\Matthew\AppData\Local\Programs\Python\Python39\lib\asyncio\proactor_events.py", line 116, in __del__
      self.close()
    File "C:\Users\Matthew\AppData\Local\Programs\Python\Python39\lib\asyncio\proactor_events.py", line 108, in close
      self._loop.call_soon(self._call_connection_lost, None)
    File "C:\Users\Matthew\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 746, in call_soon
      self._check_closed()
    File "C:\Users\Matthew\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 510, in _check_closed
      raise RuntimeError('Event loop is closed')
  RuntimeError: Event loop is closed
  
  Versions:
  playwright=1.9.2
  asyncio=3.4.3
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `playwright/_impl/_transport.py`
  Content:
  ```
  1 # Copyright (c) Microsoft Corporation.
  2 #
  3 # Licensed under the Apache License, Version 2.0 (the "License");
  4 # you may not use this file except in compliance with the License.
  5 # You may obtain a copy of the License at
  6 #
  7 # http://www.apache.org/licenses/LICENSE-2.0
  8 #
  9 # Unless required by applicable law or agreed to in writing, software
  10 # distributed under the License is distributed on an "AS IS" BASIS,
  11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 # See the License for the specific language governing permissions and
  13 # limitations under the License.
  14 
  15 import asyncio
  16 import io
  17 import json
  18 import os
  19 import sys
  20 from pathlib import Path
  21 from typing import Dict, Optional
  22 
  23 
  24 # Sourced from: https://github.com/pytest-dev/pytest/blob/da01ee0a4bb0af780167ecd228ab3ad249511302/src/_pytest/faulthandler.py#L69-L77
  25 def _get_stderr_fileno() -> Optional[int]:
  26     try:
  27         return sys.stderr.fileno()
  28     except (AttributeError, io.UnsupportedOperation):
  29         # pytest-xdist monkeypatches sys.stderr with an object that is not an actual file.
  30         # https://docs.python.org/3/library/faulthandler.html#issue-with-file-descriptors
  31         # This is potentially dangerous, but the best we can do.
  32         if not hasattr(sys, "__stderr__") or not sys.__stderr__:
  33             return None
  34         return sys.__stderr__.fileno()
  35 
  36 
  37 class Transport:
  38     def __init__(self, driver_executable: Path) -> None:
  39         super().__init__()
  40         self.on_message = lambda _: None
  41         self._stopped = False
  42         self._driver_executable = driver_executable
  43         self._loop: asyncio.AbstractEventLoop
  44 
  45     def stop(self) -> None:
  46         self._stopped = True
  47         self._output.close()
  48 
  49     async def wait_until_stopped(self) -> None:
  50         await self._stopped_future
  51 
  52     async def run(self) -> None:
  53         self._loop = asyncio.get_running_loop()
  54         self._stopped_future: asyncio.Future = asyncio.Future()
  55 
  56         proc = await asyncio.create_subprocess_exec(
  57             str(self._driver_executable),
  58             "run-driver",
  59             stdin=asyncio.subprocess.PIPE,
  60             stdout=asyncio.subprocess.PIPE,
  61             stderr=_get_stderr_fileno(),
  62             limit=32768,
  63         )
  64         assert proc.stdout
  65         assert proc.stdin
  66         self._output = proc.stdin
  67 
  68         while not self._stopped:
  69             try:
  70                 buffer = await proc.stdout.readexactly(4)
  71                 length = int.from_bytes(buffer, byteorder="little", signed=False)
  72                 buffer = bytes(0)
  73                 while length:
  74                     to_read = min(length, 32768)
  75                     data = await proc.stdout.readexactly(to_read)
  76                     length -= to_read
  77                     if len(buffer):
  78                         buffer = buffer + data
  79                     else:
  80                         buffer = data
  81                 obj = json.loads(buffer)
  82 
  83                 if "DEBUGP" in os.environ:  # pragma: no cover
  84                     print("\x1b[33mRECV>\x1b[0m", json.dumps(obj, indent=2))
  85                 self.on_message(obj)
  86             except asyncio.IncompleteReadError:
  87                 break
  88             await asyncio.sleep(0)
  89         self._stopped_future.set_result(None)
  90 
  91     def send(self, message: Dict) -> None:
  92         msg = json.dumps(message)
  93         if "DEBUGP" in os.environ:  # pragma: no cover
  94             print("\x1b[32mSEND>\x1b[0m", json.dumps(message, indent=2))
  95         data = msg.encode()
  96         self._output.write(
  97             len(data).to_bytes(4, byteorder="little", signed=False) + data
  98         )
  99
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/playwright/_impl/_transport.py b/playwright/_impl/_transport.py
  --- a/playwright/_impl/_transport.py
  +++ b/playwright/_impl/_transport.py
  @@ -48,12 +48,13 @@
   
       async def wait_until_stopped(self) -> None:
           await self._stopped_future
  +        await self._proc.wait()
   
       async def run(self) -> None:
           self._loop = asyncio.get_running_loop()
           self._stopped_future: asyncio.Future = asyncio.Future()
   
  -        proc = await asyncio.create_subprocess_exec(
  +        self._proc = proc = await asyncio.create_subprocess_exec(
               str(self._driver_executable),
               "run-driver",
               stdin=asyncio.subprocess.PIPE,
  
verification_info: {"golden_diff": "diff --git a/playwright/_impl/_transport.py b/playwright/_impl/_transport.py\n--- a/playwright/_impl/_transport.py\n+++ b/playwright/_impl/_transport.py\n@@ -48,12 +48,13 @@\n \n     async def wait_until_stopped(self) -> None:\n         await self._stopped_future\n+        await self._proc.wait()\n \n     async def run(self) -> None:\n         self._loop = asyncio.get_running_loop()\n         self._stopped_future: asyncio.Future = asyncio.Future()\n \n-        proc = await asyncio.create_subprocess_exec(\n+        self._proc = proc = await asyncio.create_subprocess_exec(\n             str(self._driver_executable),\n             \"run-driver\",\n             stdin=asyncio.subprocess.PIPE,\n", "issue": "Async API - asyncio error\nAfter updating to the 1.9.2 version, for **Async API** I get the following error:\r\n\r\nException ignored in: <function BaseSubprocessTransport.__del__ at 0x0000000002E1E9D0>\r\nTraceback (most recent call last):\r\n  File \"C:\\Users\\Matthew\\AppData\\Local\\Programs\\Python\\Python39\\lib\\asyncio\\base_subprocess.py\", line 126, in __del__\r\n    self.close()\r\n  File \"C:\\Users\\Matthew\\AppData\\Local\\Programs\\Python\\Python39\\lib\\asyncio\\base_subprocess.py\", line 104, in close  \r\n    proto.pipe.close()\r\n  File \"C:\\Users\\Matthew\\AppData\\Local\\Programs\\Python\\Python39\\lib\\asyncio\\proactor_events.py\", line 108, in close  \r\n    self._loop.call_soon(self._call_connection_lost, None)\r\n  File \"C:\\Users\\Matthew\\AppData\\Local\\Programs\\Python\\Python39\\lib\\asyncio\\base_events.py\", line 746, in call_soon\r\n    self._check_closed()\r\n  File \"C:\\Users\\Matthew\\AppData\\Local\\Programs\\Python\\Python39\\lib\\asyncio\\base_events.py\", line 510, in _check_closed\r\n    raise RuntimeError('Event loop is closed')\r\nRuntimeError: Event loop is closed\r\nException ignored in: <function _ProactorBasePipeTransport.__del__ at 0x0000000002E4A280>\r\nTraceback (most recent call last):\r\n  File \"C:\\Users\\Matthew\\AppData\\Local\\Programs\\Python\\Python39\\lib\\asyncio\\proactor_events.py\", line 116, in __del__\r\n    self.close()\r\n  File \"C:\\Users\\Matthew\\AppData\\Local\\Programs\\Python\\Python39\\lib\\asyncio\\proactor_events.py\", line 108, in close\r\n    self._loop.call_soon(self._call_connection_lost, None)\r\n  File \"C:\\Users\\Matthew\\AppData\\Local\\Programs\\Python\\Python39\\lib\\asyncio\\base_events.py\", line 746, in call_soon\r\n    self._check_closed()\r\n  File \"C:\\Users\\Matthew\\AppData\\Local\\Programs\\Python\\Python39\\lib\\asyncio\\base_events.py\", line 510, in _check_closed\r\n    raise RuntimeError('Event loop is closed')\r\nRuntimeError: Event loop is closed\r\n\r\nVersions:\r\nplaywright=1.9.2\r\nasyncio=3.4.3\n", "before_files": [{"content": "# Copyright (c) Microsoft Corporation.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport asyncio\nimport io\nimport json\nimport os\nimport sys\nfrom pathlib import Path\nfrom typing import Dict, Optional\n\n\n# Sourced from: https://github.com/pytest-dev/pytest/blob/da01ee0a4bb0af780167ecd228ab3ad249511302/src/_pytest/faulthandler.py#L69-L77\ndef _get_stderr_fileno() -> Optional[int]:\n    try:\n        return sys.stderr.fileno()\n    except (AttributeError, io.UnsupportedOperation):\n        # pytest-xdist monkeypatches sys.stderr with an object that is not an actual file.\n        # https://docs.python.org/3/library/faulthandler.html#issue-with-file-descriptors\n        # This is potentially dangerous, but the best we can do.\n        if not hasattr(sys, \"__stderr__\") or not sys.__stderr__:\n            return None\n        return sys.__stderr__.fileno()\n\n\nclass Transport:\n    def __init__(self, driver_executable: Path) -> None:\n        super().__init__()\n        self.on_message = lambda _: None\n        self._stopped = False\n        self._driver_executable = driver_executable\n        self._loop: asyncio.AbstractEventLoop\n\n    def stop(self) -> None:\n        self._stopped = True\n        self._output.close()\n\n    async def wait_until_stopped(self) -> None:\n        await self._stopped_future\n\n    async def run(self) -> None:\n        self._loop = asyncio.get_running_loop()\n        self._stopped_future: asyncio.Future = asyncio.Future()\n\n        proc = await asyncio.create_subprocess_exec(\n            str(self._driver_executable),\n            \"run-driver\",\n            stdin=asyncio.subprocess.PIPE,\n            stdout=asyncio.subprocess.PIPE,\n            stderr=_get_stderr_fileno(),\n            limit=32768,\n        )\n        assert proc.stdout\n        assert proc.stdin\n        self._output = proc.stdin\n\n        while not self._stopped:\n            try:\n                buffer = await proc.stdout.readexactly(4)\n                length = int.from_bytes(buffer, byteorder=\"little\", signed=False)\n                buffer = bytes(0)\n                while length:\n                    to_read = min(length, 32768)\n                    data = await proc.stdout.readexactly(to_read)\n                    length -= to_read\n                    if len(buffer):\n                        buffer = buffer + data\n                    else:\n                        buffer = data\n                obj = json.loads(buffer)\n\n                if \"DEBUGP\" in os.environ:  # pragma: no cover\n                    print(\"\\x1b[33mRECV>\\x1b[0m\", json.dumps(obj, indent=2))\n                self.on_message(obj)\n            except asyncio.IncompleteReadError:\n                break\n            await asyncio.sleep(0)\n        self._stopped_future.set_result(None)\n\n    def send(self, message: Dict) -> None:\n        msg = json.dumps(message)\n        if \"DEBUGP\" in os.environ:  # pragma: no cover\n            print(\"\\x1b[32mSEND>\\x1b[0m\", json.dumps(message, indent=2))\n        data = msg.encode()\n        self._output.write(\n            len(data).to_bytes(4, byteorder=\"little\", signed=False) + data\n        )\n", "path": "playwright/_impl/_transport.py"}], "after_files": [{"content": "# Copyright (c) Microsoft Corporation.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport asyncio\nimport io\nimport json\nimport os\nimport sys\nfrom pathlib import Path\nfrom typing import Dict, Optional\n\n\n# Sourced from: https://github.com/pytest-dev/pytest/blob/da01ee0a4bb0af780167ecd228ab3ad249511302/src/_pytest/faulthandler.py#L69-L77\ndef _get_stderr_fileno() -> Optional[int]:\n    try:\n        return sys.stderr.fileno()\n    except (AttributeError, io.UnsupportedOperation):\n        # pytest-xdist monkeypatches sys.stderr with an object that is not an actual file.\n        # https://docs.python.org/3/library/faulthandler.html#issue-with-file-descriptors\n        # This is potentially dangerous, but the best we can do.\n        if not hasattr(sys, \"__stderr__\") or not sys.__stderr__:\n            return None\n        return sys.__stderr__.fileno()\n\n\nclass Transport:\n    def __init__(self, driver_executable: Path) -> None:\n        super().__init__()\n        self.on_message = lambda _: None\n        self._stopped = False\n        self._driver_executable = driver_executable\n        self._loop: asyncio.AbstractEventLoop\n\n    def stop(self) -> None:\n        self._stopped = True\n        self._output.close()\n\n    async def wait_until_stopped(self) -> None:\n        await self._stopped_future\n        await self._proc.wait()\n\n    async def run(self) -> None:\n        self._loop = asyncio.get_running_loop()\n        self._stopped_future: asyncio.Future = asyncio.Future()\n\n        self._proc = proc = await asyncio.create_subprocess_exec(\n            str(self._driver_executable),\n            \"run-driver\",\n            stdin=asyncio.subprocess.PIPE,\n            stdout=asyncio.subprocess.PIPE,\n            stderr=_get_stderr_fileno(),\n            limit=32768,\n        )\n        assert proc.stdout\n        assert proc.stdin\n        self._output = proc.stdin\n\n        while not self._stopped:\n            try:\n                buffer = await proc.stdout.readexactly(4)\n                length = int.from_bytes(buffer, byteorder=\"little\", signed=False)\n                buffer = bytes(0)\n                while length:\n                    to_read = min(length, 32768)\n                    data = await proc.stdout.readexactly(to_read)\n                    length -= to_read\n                    if len(buffer):\n                        buffer = buffer + data\n                    else:\n                        buffer = data\n                obj = json.loads(buffer)\n\n                if \"DEBUGP\" in os.environ:  # pragma: no cover\n                    print(\"\\x1b[33mRECV>\\x1b[0m\", json.dumps(obj, indent=2))\n                self.on_message(obj)\n            except asyncio.IncompleteReadError:\n                break\n            await asyncio.sleep(0)\n        self._stopped_future.set_result(None)\n\n    def send(self, message: Dict) -> None:\n        msg = json.dumps(message)\n        if \"DEBUGP\" in os.environ:  # pragma: no cover\n            print(\"\\x1b[32mSEND>\\x1b[0m\", json.dumps(message, indent=2))\n        data = msg.encode()\n        self._output.write(\n            len(data).to_bytes(4, byteorder=\"little\", signed=False) + data\n        )\n", "path": "playwright/_impl/_transport.py"}]}