Created
June 14, 2024 08:03
-
-
Save zxsleebu/3602dff4be43c73e32e7d2884b7a1ac3 to your computer and use it in GitHub Desktop.
nodriver memory leak fix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from asyncio import iscoroutine, iscoroutinefunction | |
import logging | |
import json | |
import asyncio | |
import itertools | |
from nodriver import cdp | |
import nodriver as uc | |
logger = logging.getLogger("uc.connection") | |
async def listener_loop(self): | |
while True: | |
try: | |
msg = await asyncio.wait_for( | |
self.connection.websocket.recv(), self.time_before_considered_idle | |
) | |
except asyncio.TimeoutError: | |
self.idle.set() | |
# breathe | |
# await asyncio.sleep(self.time_before_considered_idle / 10) | |
continue | |
except (Exception,) as e: | |
# break on any other exception | |
# which is mostly socket is closed or does not exist | |
# or is not allowed | |
logger.debug( | |
"connection listener exception while reading websocket:\n%s", e | |
) | |
break | |
if not self.running: | |
# if we have been cancelled or otherwise stopped running | |
# break this loop | |
break | |
# since we are at this point, we are not "idle" anymore. | |
self.idle.clear() | |
message = json.loads(msg) | |
if "id" in message: | |
# response to our command | |
if message["id"] in self.connection.mapper: | |
# get the corresponding Transaction | |
tx = self.connection.mapper[message["id"]] | |
logger.debug("got answer for %s", tx) | |
# complete the transaction, which is a Future object | |
# and thus will return to anyone awaiting it. | |
tx(**message) | |
self.connection.mapper.pop(message["id"]) | |
else: | |
# probably an event | |
try: | |
event = cdp.util.parse_json_event(message) | |
event_tx = uc.connection.EventTransaction(event) | |
if not self.connection.mapper: | |
self.connection.__count__ = itertools.count(0) | |
event_tx.id = next(self.connection.__count__) | |
self.connection.mapper[event_tx.id] = event_tx | |
except Exception as e: | |
logger.info( | |
"%s: %s during parsing of json from event : %s" | |
% (type(e).__name__, e.args, message), | |
exc_info=True, | |
) | |
continue | |
except KeyError as e: | |
logger.info("some lousy KeyError %s" % e, exc_info=True) | |
continue | |
try: | |
if type(event) in self.connection.handlers: | |
callbacks = self.connection.handlers[type(event)] | |
else: | |
continue | |
if not len(callbacks): | |
continue | |
for callback in callbacks: | |
try: | |
if iscoroutinefunction(callback) or iscoroutine(callback): | |
await callback(event) | |
else: | |
callback(event) | |
except Exception as e: | |
logger.warning( | |
"exception in callback %s for event %s => %s", | |
callback, | |
event.__class__.__name__, | |
e, | |
exc_info=True, | |
) | |
raise | |
except asyncio.CancelledError: | |
break | |
except Exception: | |
raise | |
continue | |
#call this after imported nodriver | |
#uc_fix(*nodriver module*) | |
def uc_fix(uc: uc): | |
uc.core.connection.Listener.listener_loop = listener_loop |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment