Race condition when accessing sqla's pdtb_start_timer #65

Closed
lukecyca opened this Issue May 10, 2012 · 5 comments

Comments

Projects
None yet
5 participants

When running my pyramid application via waitress, simultaneous (or near-simultaeous) requests sometimes fail with:

...
  File "/Network/Cluster/home/luke/.virtualenvs/pyramid/lib/python2.6/site-packages/pyramid_debugtoolbar/panels/sqla.py", line 47, in _after_cursor_execute
    'duration': stop_timer - conn.pdtb_start_timer,
AttributeError: 'Connection' object has no attribute 'pdtb_start_timer'

I believe this is because multiple queries are executing simultaneously on the same connection, so:

  1. Query A causes the sqla panel to set pdtb_start_timer on the Connection object
  2. Query B does the same, overwriting the same attribute
  3. Query A completes, reads the attribute and deletes it
  4. Query B completes, tries to read the attribute but it's already gone

Perhaps the attribute should be stashed in the cursor object rather than the connection object, or perhaps I'm doing something majorly wrong. Unfortunately I'm stretching my knowledge of SQLAlchemy and am not in a position to submit a patch. Let me know how I can help solve this.

Owner

mcdonc commented May 11, 2012

Your analysis sounds right to me. I'm not sure what the right way to fix it is either at the moment.

Owner

mcdonc commented May 11, 2012

For what it's worth, you can work around this by setting threads = 1 in your server config in the meantime.

Thanks for the tip. That indeed works around the symptom.

cyphus commented May 23, 2017

I've attempted to reproduce this bug using the current master (commit). I've concluded that it is no longer relevant to pyramid_debugtoolbar.

Debug toolbar's SQLA panel sets the pdtb_start_timer attribute on the SQLAlchemy connection object associated with the query being ran. SQLAlchemy will default to creating one connection object per thread. This makes the pdtb_start_timer attribute effectively thread local. Even if you force SQLAlchemy to use a single connection (by passing pool_size=1, max_overflow=0 as engine arguments) you still won't be able to trigger the race condition, because SQLAlchemy's connection objects wait for one query to finish before starting another.

@lukecyca if you can provide a reproducible test case for this bug on the current version of debug toolbar, I'll be happy to look into this again. Otherwise I'm recommending this issue be closed.

Owner

bertjwregeer commented May 23, 2017

Closing, please re-open if this is still an issue. Thanks for attempting to reproduce @cyphus

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