Store sessions in individual files within a directory.
### Note There was a problem with the existing code (adopted from the Python 2 version), which lead to an "EOFError: Ran out of input" exception
The code in save_session() did:
f = open(filename, 'wb')
...which immediately made the file zero bytes long. You can try this out in 2
terminals (where s
is some dummy class with s.id
as the file-name) with one doing:
import pickle pickle.dump(s, f, 4) f.close() f = open(s.id, 'wb')
If in the other terminal you do:
f = open(s.id, 'rb') o = pickle.load(f) Traceback (most recent call last): ...EOFError: Ran out of input
This is not entirely unexpected BUT the code in load_session()
:
f = open(filename, 'rb') fcntl.flock(f.fileno(), fcntl.LOCK_SH)
...could get the shared lock (LOCK_SH) after save_session() performed
the open() but BEFORE save_session()
got a chance to get the exclusive lock:
f = open(filename, 'wb') fcntl.flock(f.fileno(), fcntl.LOCK_EX)
(You can try it in the older code by quickly refreshing a browser calling a Quixote server.)
What happened appears to have been:
- save_session() opens the file to write [f = open(filename, 'wb')]
- load_session() opens the file to read [f = open(filename, 'rb')]
- load_session() asks for and GETS a shared lock [fcntl.LOCK_SH]
- save_session() asks for an exclusive lock BUT gets blocked by the shared lock
- load_session() tries to load the object and gets zero bytes. It then closes the file, mistakenly allowing save_session() to proceed.
As save_session() truncated the file and then waited for an exclusive lock, we had to have load_session() check for a zero-sized file. If it has one, then save_session() has just created (or re-created) it and we should let go and try again.
### Addendum
It turns out that, during testing, one can get at EOFError
from pickle anyway, so a check for that was added too.
Class |
|
Store sessions in individual files within a directory. |
Constant | SLEEPY |
Undocumented |