summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_threadedtempfile.py
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-01-13 03:04:02 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-01-13 03:04:02 (GMT)
commit9fadfb0d1dbf1b42efbe1374ea55f99b57b76a3f (patch)
tree23c348d668b1045f52c2d3eedfa3b9d308eb3e34 /Lib/test/test_threadedtempfile.py
parentd7b68021ceb241fed4c082bc7a6585a987c0aab4 (diff)
downloadcpython-9fadfb0d1dbf1b42efbe1374ea55f99b57b76a3f.zip
cpython-9fadfb0d1dbf1b42efbe1374ea55f99b57b76a3f.tar.gz
cpython-9fadfb0d1dbf1b42efbe1374ea55f99b57b76a3f.tar.bz2
Guido found a brand new race in tempfile on Linux, due to Linux changing
pid across threads (but in that case, it's still the same process, and so still sharing the "template" cache in tempfile.py). Repaired that, and added a new std test. On Linux, someone please run that standalone with more files and/or more threads; e.g., python lib/test/test_threadedtempfile.py -f 1000 -t 10 to run with 10 threads each creating (and deleting) 1000 temp files.
Diffstat (limited to 'Lib/test/test_threadedtempfile.py')
-rw-r--r--Lib/test/test_threadedtempfile.py85
1 files changed, 85 insertions, 0 deletions
diff --git a/Lib/test/test_threadedtempfile.py b/Lib/test/test_threadedtempfile.py
new file mode 100644
index 0000000..a5ee12f
--- /dev/null
+++ b/Lib/test/test_threadedtempfile.py
@@ -0,0 +1,85 @@
+"""
+Create and delete FILES_PER_THREAD temp files (via tempfile.TemporaryFile)
+in each of NUM_THREADS threads, recording the number of successes and
+failures. A failure is a bug in tempfile, and may be due to:
+
++ Trying to create more than one tempfile with the same name.
++ Trying to delete a tempfile that doesn't still exist.
++ Something we've never seen before.
+
+By default, NUM_THREADS == 20 and FILES_PER_THREAD == 50. This is enough to
+create about 150 failures per run under Win98SE in 2.0, and runs pretty
+quickly. Guido reports needing to boost FILES_PER_THREAD to 500 before
+provoking a 2.0 failure under Linux. Run the test alone to boost either
+via cmdline switches:
+
+-f FILES_PER_THREAD (int)
+-t NUM_THREADS (int)
+"""
+
+NUM_THREADS = 20 # change w/ -t option
+FILES_PER_THREAD = 50 # change w/ -f option
+
+import threading
+from test.test_support import TestFailed
+import StringIO
+from traceback import print_exc
+
+startEvent = threading.Event()
+
+import tempfile
+tempfile.gettempdir() # Do this now, to avoid spurious races later
+
+class TempFileGreedy(threading.Thread):
+ error_count = 0
+ ok_count = 0
+
+ def run(self):
+ self.errors = StringIO.StringIO()
+ startEvent.wait()
+ for i in range(FILES_PER_THREAD):
+ try:
+ f = tempfile.TemporaryFile("w+b")
+ f.close()
+ except:
+ self.error_count += 1
+ print_exc(file=self.errors)
+ else:
+ self.ok_count += 1
+
+def _test():
+ threads = []
+
+ print "Creating"
+ for i in range(NUM_THREADS):
+ t = TempFileGreedy()
+ threads.append(t)
+ t.start()
+
+ print "Starting"
+ startEvent.set()
+
+ print "Reaping"
+ ok = errors = 0
+ for t in threads:
+ t.join()
+ ok += t.ok_count
+ errors += t.error_count
+ if t.error_count:
+ print '%s errors:\n%s' % (t.getName(), t.errors.getvalue())
+
+ msg = "Done: errors %d ok %d" % (errors, ok)
+ print msg
+ if errors:
+ raise TestFailed(msg)
+
+if __name__ == "__main__":
+ import sys, getopt
+ opts, args = getopt.getopt(sys.argv[1:], "t:f:")
+ for o, v in opts:
+ if o == "-f":
+ FILES_PER_THREAD = int(v)
+ elif o == "-t":
+ NUM_THREADS = int(v)
+
+_test()