Skip to content
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

TypeError: 'Context' object is not callable #7856

Open
sentry-for-tribler bot opened this issue Jan 25, 2024 · 4 comments
Open

TypeError: 'Context' object is not callable #7856

sentry-for-tribler bot opened this issue Jan 25, 2024 · 4 comments

Comments

@sentry-for-tribler
Copy link

Sentry Issue: TRIBLER-1J6

Traceback (most recent call last):, 
  File "asyncio\events.py", line 81, in _run, 
TypeError: 'Context' object is not callable
@xoriole xoriole added this to the 7.14.0 milestone Jan 25, 2024
@drew2a drew2a self-assigned this Jan 25, 2024
@drew2a
Copy link
Collaborator

drew2a commented Jan 25, 2024

It's challenging to determine what is happening in this event with only the provided stack trace.

However, in the arguments, we can see '"Notifier._notify(<function pee...001299E73DA60>, <bound method...0129A107CC40>>, (b\'\\\\x00\\\\x00\\\\x0...0\\\\x00\\\\x00\\\\x00\'), {})"', which could hint that there is a notifier call where the first argument's type is bytes. If we assume that the passed argument is of the correct type, then the main suspicion falls on the following event:

def peer_disconnected(peer_id: bytes):
    ...

But I believe that this event is just a random event.
Moving forward...
The _run function of asyncio has the following listing:

    def _run(self):
        try:
            self._context.run(self._callback, *self._args)
        except (SystemExit, KeyboardInterrupt):
            raise
        except BaseException as exc:
            cb = format_helpers._format_callback_source(
                self._callback, self._args)
            msg = f'Exception in callback {cb}'
            context = {
                'message': msg,
                'exception': exc,
                'handle': self,
            }
            if self._source_traceback:
                context['source_traceback'] = self._source_traceback
            self._loop.call_exception_handler(context)
        self = None  # Needed to break cycles when an exception occurs.

But we are patching the original asyncio _run by:

def patched_handle_run(self: Handle):
"""
Remembers the current asyncio handle object and its starting time globally, so it becomes possible
to access it from the separate thread and detect slow coroutines.
"""
start_time = time.time()
with lock:
current.handle, current.start_time = self, start_time
try:
_original_handle_run(self)
finally:
with lock:
current.handle = current.start_time = None
duration = time.time() - start_time
if duration > SLOW_CORO_DURATION_THRESHOLD:
# The coroutine step is finished successfully (without freezing), but the execution time was too long
_report_long_duration(self, duration)
self = None # Needed to break cycles when an exception occurs (copied from the original Handle._run method)

The candidate for a Context class is the following: https://docs.python.org/3/library/contextvars.html#contextvars.Context

At the moment, my best guess is that the problem is not related to the notifier itself, but rather to asyncio or the way we are modifying it.

@drew2a
Copy link
Collaborator

drew2a commented Jan 25, 2024

@kozlovsky, as the author of the asyncio patch, could you please have a quick look at it?

@kozlovsky
Copy link
Collaborator

Looks strange. I can't preclude that the error results from someone's experiments with the Tribler code. I'd suggest waiting until we have a second case of this error to be sure it is an actual error and not the result of running a modified code.

Some additional observations:

  1. In the Notifier code, it is possible to register an incorrect generic observer that is not a callable. However, possible exceptions should be caught inside the _notify method, so it can't be the reason for the current error:

    def _notify(self, topic: Callable, observer: Callable, args: tuple, kwargs: dict):
        self.logger.debug(f"Calling observer {observer!r} for topic {topic.__name__}")
        try:
            observer(*args, **kwargs)  # <-- here
        except Exception as e:  # pylint: disable=broad-except
            self.logger.exception(e)
  2. It indeed looks like the notification is peer_disconnected, and it is interesting that peer_id only appears to consist of zero bytes. I don't know how normal it is, and it may be an additional hint on what is going on.

@drew2a drew2a removed their assignment Jan 29, 2024
Copy link

This issue has not seen activity for 60 days. It is now marked as stale. Please provide additional information or this issue may be closed in the future. We value your contribution and would love to hear more!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants