Last active
December 14, 2015 08:58
-
-
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…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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