I think there is another bug as well.
The _unlock function only unlocks the session file if it exists but leaves
response.session_file defined.
Later when the request cycle finishes the _try_store_on_disk function will
still see response.session_file as active and write it but this is now
dangerous because it was unlocked before the write and a second request from
the same client machine could clash. This has also had the fortunate side
effect of closing the session file so the server does not leak file
descriptors.
I think the tail end of _try_store_on_disk and _unlock should look like
this:
if response.session_file:
cPickle.dump(dict(self), response.session_file)
response.session_file.truncate()
self._unlock(response)
def _unlock(self, response):
if response and response.session_file:
try:
portalocker.unlock(response.session_file)
response.session_file.close()
del response.session_file
except: ### this should never happen but happens in Windows
pass
But the del response.session_file will cause an AttributeError exception so
maybe it would be better to set it to None or change all the tests for
response.session_file to be hasattr(response, 'session_file')
Ron