Skip to content

Instantly share code, notes, and snippets.

@valtron
Last active December 14, 2015 08:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save valtron/5061395 to your computer and use it in GitHub Desktop.
Save valtron/5061395 to your computer and use it in GitHub Desktop.
Replicates concurrency bug described in https://github.com/mitsuhiko/jinja2/issues/8 using two threads. `MyLRUCache` implements a fix using a lock. The first commandline argument is the amount of time to sleep between accesses to the cache. If set to 0, it triggers the bug almost right away. If set to 0.001 (the smallest nonzero value sleep will…
from threading import Thread
from time import sleep, time
from random import choice, random
from jinja2.utils import LRUCache
class MyLRUCache(LRUCache):
def __getitem__(self, key):
self._wlock.acquire()
try:
return super(MyLRUCache, self).__getitem__(key)
finally:
self._wlock.release()
SIZE = 10
t0 = None
keys = 'abcdefghijklmnopqrstuvwxyz'
sleep_time = None
#d = LRUCache(SIZE)
d = MyLRUCache(SIZE)
def main(t):
global sleep_time
global t0
sleep_time = t
t0 = time()
for _ in xrange(2):
t = Thread(target = f)
t.start()
def f():
try:
while True:
k = choice(keys)
if random() > 0.1:
try:
d[k]
except KeyError:
# This is ignorable, we might not have actually inserted this key
pass
else:
d[k] = 1
sleep(sleep_time)
finally:
print "Ran for {} seconds before failing".format(time() - t0)
if __name__ == '__main__':
from sys import argv
if len(argv) == 2:
t = float(argv[1])
else:
t = 0
main(t)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment