module documentation

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:

  1. save_session() opens the file to write [f = open(filename, 'wb')]
  2. load_session() opens the file to read [f = open(filename, 'rb')]
  3. load_session() asks for and GETS a shared lock [fcntl.LOCK_SH]
  4. save_session() asks for an exclusive lock BUT gets blocked by the shared lock
  5. 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 DirectorySessionStore Store sessions in individual files within a directory.
Constant SLEEPY_TIME Undocumented
SLEEPY_TIME: float =

Undocumented

Value
0.1