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

RecursionError if many calls were waiting for free connection #106

Open
IlyaSkriblovsky opened this issue Mar 17, 2016 · 1 comment
Open

Comments

@IlyaSkriblovsky
Copy link
Owner

This code either hangs (py2) or crashes with RecursionError (py3):

from __future__ import print_function

@defer.inlineCallbacks
def main():
    redis = txredisapi.lazyConnection()
    redis.set('c', 0)

    yield defer.gatherResults(
        redis.incr('c').addCallback(print)
        for i in range(0, 1000)
    )

Each non-blocking call to Redis does connectionQueue.get() to get connection and then immediately does connectionQueue.put() because it's non-blocking. If there are other pending calls, DeferredQueue.put() immediately passes released connection to next pending call in same execution stack. This next call in its turn immediately calls connectionQueue.put() again.

So, if many queries were waiting for free connection (because either connection wasn't made yet like in code above or it is blocked by transaction), when connection is ready, all these queries will be processed recursively in a single execution stack. Default Python's recursion limit of 1000 gets exhausted after processing 73–74 queries.

The dumb solution: replace
self._factory.connectionQueue.put(connection) (txredisapi.py:1864)
by reactor.callLater(0, self._factory.connectionQueue.put, connection)
This solves the issue, but is very ugly.

@IlyaSkriblovsky
Copy link
Owner Author

Much nicer solution is in #107

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

No branches or pull requests

1 participant