| 
									
										
										
										
											2001-05-22 09:34:27 +00:00
										 |  |  | # This is a variant of the very old (early 90's) file | 
					
						
							|  |  |  | # Demo/threads/bug.py.  It simply provokes a number of threads into | 
					
						
							|  |  |  | # trying to import the same module "at the same time". | 
					
						
							|  |  |  | # There are no pleasant failure modes -- most likely is that Python | 
					
						
							|  |  |  | # complains several times about module random having no attribute | 
					
						
							|  |  |  | # randrange, and then Python hangs. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import thread | 
					
						
							| 
									
										
										
										
											2006-04-21 21:18:10 +00:00
										 |  |  | from test.test_support import verbose, TestSkipped, TestFailed | 
					
						
							| 
									
										
										
										
											2001-05-22 09:34:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | critical_section = thread.allocate_lock() | 
					
						
							|  |  |  | done = thread.allocate_lock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def task(): | 
					
						
							|  |  |  |     global N, critical_section, done | 
					
						
							|  |  |  |     import random | 
					
						
							|  |  |  |     x = random.randrange(1, 3) | 
					
						
							|  |  |  |     critical_section.acquire() | 
					
						
							|  |  |  |     N -= 1 | 
					
						
							| 
									
										
										
										
											2002-02-16 07:26:27 +00:00
										 |  |  |     # Must release critical_section before releasing done, else the main | 
					
						
							|  |  |  |     # thread can exit and set critical_section to None as part of global | 
					
						
							|  |  |  |     # teardown; then critical_section.release() raises AttributeError. | 
					
						
							|  |  |  |     finished = N == 0 | 
					
						
							| 
									
										
										
										
											2001-05-22 09:34:27 +00:00
										 |  |  |     critical_section.release() | 
					
						
							| 
									
										
										
										
											2002-02-16 07:26:27 +00:00
										 |  |  |     if finished: | 
					
						
							|  |  |  |         done.release() | 
					
						
							| 
									
										
										
										
											2001-05-22 09:34:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-21 21:18:10 +00:00
										 |  |  | def test_import_hangers(): | 
					
						
							|  |  |  |     import sys | 
					
						
							|  |  |  |     if verbose: | 
					
						
							|  |  |  |         print "testing import hangers ...", | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-19 08:14:28 +00:00
										 |  |  |     import test.threaded_import_hangers | 
					
						
							| 
									
										
										
										
											2006-04-21 21:18:10 +00:00
										 |  |  |     try: | 
					
						
							| 
									
										
										
										
											2006-06-19 08:14:28 +00:00
										 |  |  |         if test.threaded_import_hangers.errors: | 
					
						
							|  |  |  |             raise TestFailed(test.threaded_import_hangers.errors) | 
					
						
							| 
									
										
										
										
											2006-04-21 21:18:10 +00:00
										 |  |  |         elif verbose: | 
					
						
							|  |  |  |             print "OK." | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         # In case this test is run again, make sure the helper module | 
					
						
							|  |  |  |         # gets loaded from scratch again. | 
					
						
							|  |  |  |         del sys.modules['test.threaded_import_hangers'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-05-22 18:28:25 +00:00
										 |  |  | # Tricky:  When regrtest imports this module, the thread running regrtest | 
					
						
							|  |  |  | # grabs the import lock and won't let go of it until this module returns. | 
					
						
							|  |  |  | # All other threads attempting an import hang for the duration.  Since | 
					
						
							|  |  |  | # this test spawns threads that do little *but* import, we can't do that | 
					
						
							|  |  |  | # successfully until after this module finishes importing and regrtest | 
					
						
							|  |  |  | # regains control.  To make this work, a special case was added to | 
					
						
							|  |  |  | # regrtest to invoke a module's "test_main" function (if any) after | 
					
						
							|  |  |  | # importing it. | 
					
						
							| 
									
										
										
										
											2001-05-22 09:34:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-05-22 18:28:25 +00:00
										 |  |  | def test_main():        # magic name!  see above | 
					
						
							| 
									
										
										
										
											2001-05-22 09:34:27 +00:00
										 |  |  |     global N, done | 
					
						
							| 
									
										
										
										
											2001-08-30 05:16:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     import imp | 
					
						
							|  |  |  |     if imp.lock_held(): | 
					
						
							|  |  |  |         # This triggers on, e.g., from test import autotest. | 
					
						
							|  |  |  |         raise TestSkipped("can't run when import lock is held") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-05-22 09:34:27 +00:00
										 |  |  |     done.acquire() | 
					
						
							| 
									
										
										
										
											2001-05-22 18:28:25 +00:00
										 |  |  |     for N in (20, 50) * 3: | 
					
						
							|  |  |  |         if verbose: | 
					
						
							|  |  |  |             print "Trying", N, "threads ...", | 
					
						
							| 
									
										
										
										
											2001-05-22 09:34:27 +00:00
										 |  |  |         for i in range(N): | 
					
						
							|  |  |  |             thread.start_new_thread(task, ()) | 
					
						
							|  |  |  |         done.acquire() | 
					
						
							| 
									
										
										
										
											2001-05-22 18:28:25 +00:00
										 |  |  |         if verbose: | 
					
						
							|  |  |  |             print "OK." | 
					
						
							| 
									
										
										
										
											2004-08-03 10:45:59 +00:00
										 |  |  |     done.release() | 
					
						
							| 
									
										
										
										
											2001-05-22 09:34:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-21 21:18:10 +00:00
										 |  |  |     test_import_hangers() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-05-22 18:28:25 +00:00
										 |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     test_main() |