Skip to content

#434 breaks on threads where run is not a method #487

Closed
@bfontaine

Description

@bfontaine

The patching code added in #434 breaks if the run attribute on a thread is not a method.

I’m using sentry-sdk==0.11.1 with Python 3.7.4.

Put the following code in demo.py:

import sentry_sdk
from sentry_sdk.integrations.threading import ThreadingIntegration

sentry_sdk.init(default_integrations=False, integrations=[ThreadingIntegration()])

from threading import Thread

class MyThread(Thread):
    def __init__(self):
        super().__init__()
        self.run = lambda: print("hello")

t = MyThread()
t.start()
t.join()

Run python3 demo.py:

Traceback (most recent call last):
  File "demo.py", line 18, in <module>
    t.start()
  File "/myapp/venv/lib/python3.7/site-packages/sentry_sdk/integrations/threading.py", line 41, in sentry_start
    self.run = _wrap_run(hub_, self.run.__func__)
AttributeError: 'function' object has no attribute '__func__'

Remove Sentry:

from threading import Thread

class MyThread(Thread):
    def __init__(self):
        super().__init__()
        self.run = lambda: print("hello")

t = MyThread()
t.start()
t.join()

Run it again: python3 demo.py

hello

It runs fine.


The issue is that the patching code relies on self.run.__func__ but that attribute is only defined on methods, not on functions.

You can see that with this code:

>>> class A():
...     def f(self):
...             pass
...     def set_f(self):
...             self.f = lambda _: 42
...
>>> a = A()
>>> a.f.__func__
<function A.f at 0x106dfaef0>
>>> a.set_f()
>>> a.f.__func__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '__func__'

According to the Python docs, one can call inspect.ismethod on an object to check if it’s a method and so if it has a ___func__ attribute (you could even use hasattr).

I haven’t tested it, but I believe something like this would do the job:

run_function = self.run.__func__ if inspect.ismethod(self.run) else self.run
self.run = _wrap_run(hub_, run_function)

Note that this self.run assigment code (already in the patch) transforms self.run in a function rather than a method if it were one before, meaning that in my example code MyThread().run.__func__ is defined only if I don’t use Sentry (or at least its Thread integration).


What do you think? I can move forward and make a pull-request with a test and a fix if the solution above suits you.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions