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

Infinite recursion when logging from a property #6122

Closed
jcsteh opened this Issue Jun 29, 2016 · 1 comment

Comments

Projects
None yet
1 participant
@jcsteh
Contributor

jcsteh commented Jun 29, 2016

STR:

  1. Open the NVDA Python console.

  2. Type the following:

    class C(object):
      @property
        def p(self):
          log.info("p", stack_info=True)
    
    C().p
    
  3. Look at the log.

You get something like this:

  File "<console>", line 4, in p
  File "C:\Python27\lib\logging\__init__.py", line 1159, in info
    self._log(INFO, msg, args, **kwargs)
  File "logHandler.py", line 91, in _log
    codepath=getCodePath(f)
  File "logHandler.py", line 55, in getCodePath
    attr=getattr(arg0,funcName)
  File "<console>", line 4, in p
  File "C:\Python27\lib\logging\__init__.py", line 1159, in info
    self._log(INFO, msg, args, **kwargs)
  File "logHandler.py", line 91, in _log
    codepath=getCodePath(f)
  File "logHandler.py", line 55, in getCodePath
    attr=getattr(arg0,funcName)
  File "<console>", line 4, in p
  File "C:\Python27\lib\logging\__init__.py", line 1159, in info
    self._log(INFO, msg, args, **kwargs)
  File "logHandler.py", line 91, in _log
    codepath=getCodePath(f)
  File "logHandler.py", line 55, in getCodePath
    attr=getattr(arg0,funcName)
...

And so the recursion continues. The reason is that logHandler.getCodePath retrieves the p attribute from the class, but in this case, the attribute is a property. Retrieving the property runs the logging code again... and thus begins the infinite recursion. I'm pretty sure we exceed maximum recursion depth, but getCodePath catches that exception.

As to why we aren't hitting this all the time, I think this only applies to properties which use decorators. In contrast, most of our properties use the _get_foo magic methods, and in that case, the function name from the code attribute will point at the _get_foo method, not the foo property itself. So, we've just been lucky enough not to log within a decorated property.

We should be able to solve this by trying to retrieve the attribute from the class first. If that attribute has a __get__ attribute, we know it's a descriptor (usually a property). If so, we shouldn't try to retrieve the attribute from the instance.

@jcsteh

This comment has been minimized.

Show comment
Hide comment
Contributor

jcsteh commented Jun 29, 2016

@jcsteh jcsteh added the p1 label Jul 1, 2016

@jcsteh jcsteh added this to the 2016.3 milestone Jul 1, 2016

michaelDCurran added a commit that referenced this issue Jul 7, 2016

logHandler.getCodePath: Avoid fetching an attribute from an object in…
… infinite recursion if that attribute is a property. Also choose the actual class the function was defined on, rather than the sub most class of the object.

Fixes #6122

michaelDCurran added a commit that referenced this issue Jul 24, 2016

logHandler.getCodePath: Avoid fetching an attribute from an object in…
… infinite recursion if that attribute is a property. Also choose the actual class the function was defined on, rather than the sub most class of the object. (#6151)

Fixes #6122
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment