Close a potentially unclosed body file before it can interfere with writing a new one#343
Close a potentially unclosed body file before it can interfere with writing a new one#343A5rocks wants to merge 1 commit intopsf:masterfrom
Conversation
| new_headers = {} | ||
| if not resp: | ||
| return {} | ||
| with resp: |
There was a problem hiding this comment.
I'm scratching my head why unraisablehook isn't detecting this missing with. Perhaps requests is closing the connection on GC without issuing a ResourceWarning?
There was a problem hiding this comment.
It's also possible a SeparateBodyCache isn't used in the tests (I haven't checked)?
There was a problem hiding this comment.
I think test_body_actually_stored_separately doesn't test the case where theres an outdated entry in cache, which is when a ResourceWarning should appear.
Otherwise, conditional_headers either:
- doesn't have a resp (so no body file to warn)
- gets shortcircuited around. see
cachecontrol/cachecontrol/adapter.py
Lines 70 to 74 in 34564d8
though I'm not completely sure, cause test_update_cached_response_with_valid_headers_separate_body looks like it tests that case...
This is based on debugging in python-trio/trio#3127 and some comments from @graingert, so see that PR for specific information on what was failing (I minimized a failing example) and testing this fix for it (latest commit). Just look at the relevant github actions logs.
This problem only manifests on the combination of PyPy and Windows. Here's how:
CacheControlAdapter#sendcallsconditional_headersconditional_headerscalls_load_from_cache_load_from_cachecallsbody_file = self.cache.get_body(cache_url)and saves it to the responseget_bodyreturns anopened fileconditional_headersuses the response (which holds the body file) to get headersconditional_headersreturns, but doesn't explicitly finish the requestCacheControlAdapter#sendnow runssuper().send(request, stream, timeout, verify, cert, proxies)os.replaceitThus an annoying caching bug happens. Hopefully I've described it well enough.
Note that this might only happen with
pip'sSafeFileCache(which is a subclass ofSeparateBodyBaseCache). Some of the details rely onos.replaceetc which doesn't happen here. But the fix applies here so...