You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3835 lines
117 KiB

Merged revisions 64623,64640,64665,64687,64689-64690,64719,64721,64735,64742,64744-64746,64756-64761,64767-64769,64771-64772,64774-64775,64788,64793,64835-64836 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r64623 | benjamin.peterson | 2008-07-01 21:51:54 +0200 (Tue, 01 Jul 2008) | 1 line write a short little section for multiprocessing; it still needs help ........ r64640 | georg.brandl | 2008-07-01 22:56:03 +0200 (Tue, 01 Jul 2008) | 2 lines Add a comment about incref'ing w. ........ r64665 | jesse.noller | 2008-07-02 18:56:51 +0200 (Wed, 02 Jul 2008) | 1 line Add #!/usr/bin/env python for ben ........ r64687 | andrew.kuchling | 2008-07-03 14:50:03 +0200 (Thu, 03 Jul 2008) | 1 line Tweak wording ........ r64689 | benjamin.peterson | 2008-07-03 14:57:35 +0200 (Thu, 03 Jul 2008) | 1 line lowercase glossary term ........ r64690 | benjamin.peterson | 2008-07-03 15:01:17 +0200 (Thu, 03 Jul 2008) | 1 line let the term be linked ........ r64719 | raymond.hettinger | 2008-07-05 04:11:55 +0200 (Sat, 05 Jul 2008) | 1 line Update comment on prediction macros. ........ r64721 | georg.brandl | 2008-07-05 12:07:18 +0200 (Sat, 05 Jul 2008) | 2 lines Fix tabs. ........ r64735 | mark.dickinson | 2008-07-05 17:25:48 +0200 (Sat, 05 Jul 2008) | 3 lines Minor rewrite of cmath_log to work around a Sun compiler bug. See issue #3168. ........ r64742 | benjamin.peterson | 2008-07-05 18:29:38 +0200 (Sat, 05 Jul 2008) | 1 line make regrtest aware of the lib2to3 resource ........ r64744 | georg.brandl | 2008-07-05 18:43:45 +0200 (Sat, 05 Jul 2008) | 2 lines Keep below 80 chars. ........ r64745 | facundo.batista | 2008-07-05 21:19:50 +0200 (Sat, 05 Jul 2008) | 3 lines Issue 3289. Removed two lines that ended doing nothing. ........ r64746 | facundo.batista | 2008-07-05 22:39:59 +0200 (Sat, 05 Jul 2008) | 4 lines Issue #3239. Differentiate the ascii call from the curses one and the builtin one. ........ r64756 | gregory.p.smith | 2008-07-06 09:16:40 +0200 (Sun, 06 Jul 2008) | 3 lines - Issue #2113: Fix error in subprocess.Popen if the select system call is interrupted by a signal. ........ r64757 | benjamin.peterson | 2008-07-06 14:39:09 +0200 (Sun, 06 Jul 2008) | 1 line remove test_compact_freelists from test_sys ........ r64758 | gregory.p.smith | 2008-07-06 19:06:29 +0200 (Sun, 06 Jul 2008) | 2 lines fix issue3304 - remove an incorrect PyMem_Free in fileio_init ........ r64759 | georg.brandl | 2008-07-06 19:36:20 +0200 (Sun, 06 Jul 2008) | 2 lines Fix opensearch template. ........ r64760 | andrew.kuchling | 2008-07-06 19:43:16 +0200 (Sun, 06 Jul 2008) | 1 line Wording fix ........ r64761 | andrew.kuchling | 2008-07-06 19:44:17 +0200 (Sun, 06 Jul 2008) | 1 line Add two items; rewrap paragraph ........ r64767 | gregory.p.smith | 2008-07-07 06:31:58 +0200 (Mon, 07 Jul 2008) | 4 lines - Issue #3309: Fix bz2.BZFile itererator to release its internal lock properly when raising an exception due to the bz2file being closed. Prevents a deadlock. ........ r64768 | josiah.carlson | 2008-07-07 06:51:46 +0200 (Mon, 07 Jul 2008) | 2 lines Fixed bugs 760475, 953599, and 1519. ........ r64769 | gregory.p.smith | 2008-07-07 06:54:31 +0200 (Mon, 07 Jul 2008) | 2 lines Add commented out #_sha256 and #_sha512 lines per issue 3183. ........ r64771 | gregory.p.smith | 2008-07-07 07:09:12 +0200 (Mon, 07 Jul 2008) | 4 lines - Issue #3094: httplib.HTTPSConnection Host: headers no longer include the redundant ":443" port number designation when the connection is using the default https port (443). ........ r64772 | skip.montanaro | 2008-07-07 13:16:14 +0200 (Mon, 07 Jul 2008) | 2 lines Correct grammar. ........ r64774 | andrew.kuchling | 2008-07-07 18:51:09 +0200 (Mon, 07 Jul 2008) | 1 line Fix example to match text ........ r64775 | facundo.batista | 2008-07-07 19:02:59 +0200 (Mon, 07 Jul 2008) | 3 lines Issue 3306. Better control for a lenght in findmax() function. ........ r64788 | georg.brandl | 2008-07-08 09:05:23 +0200 (Tue, 08 Jul 2008) | 2 lines Add missing ABCs to list. ........ r64793 | nick.coghlan | 2008-07-08 16:21:42 +0200 (Tue, 08 Jul 2008) | 1 line Add missing NEWS and ACK entries for r64791 ........ r64835 | raymond.hettinger | 2008-07-10 11:31:08 +0200 (Thu, 10 Jul 2008) | 1 line Issue 3287: Raise correct exception for float inputs. ........ r64836 | raymond.hettinger | 2008-07-10 12:28:41 +0200 (Thu, 10 Jul 2008) | 1 line Use operator.index() instead of n.__index__(). ........
18 years ago
Merged revisions 70734,70775,70856,70874,70876-70877 via svnmerge ........ r70734 | r.david.murray | 2009-03-30 15:04:00 -0400 (Mon, 30 Mar 2009) | 7 lines Add import_function method to test.test_support, and modify a number of tests that expect to be skipped if imports fail or functions don't exist to use import_function and import_module. The ultimate goal is to change regrtest to not skip automatically on ImportError. Checking in now to make sure the buldbots don't show any errors on platforms I can't direct test on. ........ r70775 | r.david.murray | 2009-03-30 19:05:48 -0400 (Mon, 30 Mar 2009) | 4 lines Change more tests to use import_module for the modules that should cause tests to be skipped. Also rename import_function to the more descriptive get_attribute and add a docstring. ........ r70856 | r.david.murray | 2009-03-31 14:32:17 -0400 (Tue, 31 Mar 2009) | 7 lines A few more test skips via import_module, and change import_module to return the error message produced by importlib, so that if an import in the package whose import is being wrapped is what failed the skip message will contain the name of that module instead of the name of the wrapped module. Also fixed formatting of some previous comments. ........ r70874 | r.david.murray | 2009-03-31 15:33:15 -0400 (Tue, 31 Mar 2009) | 5 lines Improve test_support.import_module docstring, remove deprecated flag from get_attribute since it isn't likely to do anything useful. ........ r70876 | r.david.murray | 2009-03-31 15:49:15 -0400 (Tue, 31 Mar 2009) | 4 lines Remove the regrtest check that turns any ImportError into a skipped test. Hopefully all modules whose imports legitimately result in a skipped test have been properly wrapped by the previous commits. ........ r70877 | r.david.murray | 2009-03-31 15:57:24 -0400 (Tue, 31 Mar 2009) | 2 lines Add NEWS entry for regrtest change. ........
17 years ago
Merged revisions 70734,70775,70856,70874,70876-70877 via svnmerge ........ r70734 | r.david.murray | 2009-03-30 15:04:00 -0400 (Mon, 30 Mar 2009) | 7 lines Add import_function method to test.test_support, and modify a number of tests that expect to be skipped if imports fail or functions don't exist to use import_function and import_module. The ultimate goal is to change regrtest to not skip automatically on ImportError. Checking in now to make sure the buldbots don't show any errors on platforms I can't direct test on. ........ r70775 | r.david.murray | 2009-03-30 19:05:48 -0400 (Mon, 30 Mar 2009) | 4 lines Change more tests to use import_module for the modules that should cause tests to be skipped. Also rename import_function to the more descriptive get_attribute and add a docstring. ........ r70856 | r.david.murray | 2009-03-31 14:32:17 -0400 (Tue, 31 Mar 2009) | 7 lines A few more test skips via import_module, and change import_module to return the error message produced by importlib, so that if an import in the package whose import is being wrapped is what failed the skip message will contain the name of that module instead of the name of the wrapped module. Also fixed formatting of some previous comments. ........ r70874 | r.david.murray | 2009-03-31 15:33:15 -0400 (Tue, 31 Mar 2009) | 5 lines Improve test_support.import_module docstring, remove deprecated flag from get_attribute since it isn't likely to do anything useful. ........ r70876 | r.david.murray | 2009-03-31 15:49:15 -0400 (Tue, 31 Mar 2009) | 4 lines Remove the regrtest check that turns any ImportError into a skipped test. Hopefully all modules whose imports legitimately result in a skipped test have been properly wrapped by the previous commits. ........ r70877 | r.david.murray | 2009-03-31 15:57:24 -0400 (Tue, 31 Mar 2009) | 2 lines Add NEWS entry for regrtest change. ........
17 years ago
Merged revisions 80552-80556,80564-80566,80568-80571 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r80552 | victor.stinner | 2010-04-27 23:46:03 +0200 (mar., 27 avril 2010) | 3 lines Issue #7449, part 1: fix test_support.py for Python compiled without thread ........ r80553 | victor.stinner | 2010-04-27 23:47:01 +0200 (mar., 27 avril 2010) | 1 line Issue #7449, part 2: regrtest.py -j option requires thread support ........ r80554 | victor.stinner | 2010-04-27 23:51:26 +0200 (mar., 27 avril 2010) | 9 lines Issue #7449 part 3, test_doctest: import trace module in test_coverage() Import trace module fail if the threading module is missing. test_coverage() is only used if test_doctest.py is used with the -c option. This commit allows to execute the test suite without thread support. Move "import trace" in test_coverage() and use test_support.import_module('trace'). ........ r80555 | victor.stinner | 2010-04-27 23:56:26 +0200 (mar., 27 avril 2010) | 6 lines Issue #7449, part 4: skip test_multiprocessing if thread support is disabled import threading after _multiprocessing to raise a more revelant error message: "No module named _multiprocessing". _multiprocessing is not compiled without thread support. ........ r80556 | victor.stinner | 2010-04-28 00:01:24 +0200 (mer., 28 avril 2010) | 8 lines Issue #7449, part 5: split Test.test_open() of ctypes/test/test_errno.py * Split Test.test_open() in 2 functions: test_open() and test_thread_open() * Skip test_open() and test_thread_open() if we are unable to find the C library * Skip test_thread_open() if thread support is disabled * Use unittest.skipUnless(os.name == "nt", ...) on test_GetLastError() ........ r80564 | victor.stinner | 2010-04-28 00:59:35 +0200 (mer., 28 avril 2010) | 4 lines Issue #7449, part 6: fix test_hashlib for missing threading module Move @test_support.reap_thread decorator from test_main() to test_threaded_hashing(). ........ r80565 | victor.stinner | 2010-04-28 01:01:29 +0200 (mer., 28 avril 2010) | 6 lines Issue #7449, part 7: simplify threading detection in test_capi * Skip TestPendingCalls if threading module is missing * Test if threading module is present or not, instead of test the presence of _testcapi._test_thread_state ........ r80566 | victor.stinner | 2010-04-28 01:03:16 +0200 (mer., 28 avril 2010) | 4 lines Issue #7449, part 8: don't skip the whole test_asynchat if threading is missing TestFifo can be executed without the threading module ........ r80568 | victor.stinner | 2010-04-28 01:14:58 +0200 (mer., 28 avril 2010) | 6 lines Issue #7449, part 9: fix test_xmlrpclib for missing threading module * Skip testcases using threads if threading module is missing * Use "http://" instead of URL in ServerProxyTestCase if threading is missing because URL is not set in this case ........ r80569 | victor.stinner | 2010-04-28 01:33:58 +0200 (mer., 28 avril 2010) | 6 lines Partial revert of r80556 (Issue #7449, part 5, fix ctypes test) Rewrite r80556: the thread test have to be executed just after the test on libc_open() and so the test cannot be splitted in two functions (without duplicating code, and I don't want to duplicate code). ........ r80570 | victor.stinner | 2010-04-28 01:51:16 +0200 (mer., 28 avril 2010) | 8 lines Issue #7449, part 10: test_cmd imports trace module using test_support.import_module() Use test_support.import_module() instead of import to raise a SkipTest exception if the import fail. Import trace fails if the threading module is missing. See also part 3: test_doctest: import trace module in test_coverage(). ........ r80571 | victor.stinner | 2010-04-28 01:55:59 +0200 (mer., 28 avril 2010) | 6 lines Issue #7449, last part (11): fix many tests if thread support is disabled * Use try/except ImportError or test_support.import_module() to import thread and threading modules * Add @unittest.skipUnless(threading, ...) to testcases using threads ........
16 years ago
Merged revisions 73995,74002,74005,74007-74008,74011,74019-74023 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r73995 | vinay.sajip | 2009-07-13 07:21:05 -0400 (Mon, 13 Jul 2009) | 1 line Issue #6314: logging: Extra checks on the "level" argument in more places. ........ r74002 | marc-andre.lemburg | 2009-07-13 16:23:49 -0400 (Mon, 13 Jul 2009) | 6 lines Use a new global DEV_NULL instead of hard-coding /dev/null into the system command helper functions. See #6479 for some motivation. ........ r74005 | marc-andre.lemburg | 2009-07-13 17:28:33 -0400 (Mon, 13 Jul 2009) | 6 lines Use a different VER command output parser to address the localization issues mentioned in #3410. Prepare for Windows 7 (still commented out). ........ r74007 | michael.foord | 2009-07-14 13:58:12 -0400 (Tue, 14 Jul 2009) | 1 line Move TestRunner initialisation into unittest.TestProgram.runTests. Fixes issue 6418. ........ r74008 | benjamin.peterson | 2009-07-14 20:46:42 -0400 (Tue, 14 Jul 2009) | 1 line update year ........ r74011 | ezio.melotti | 2009-07-15 13:07:04 -0400 (Wed, 15 Jul 2009) | 1 line methods' names pep8ification ........ r74019 | amaury.forgeotdarc | 2009-07-15 17:29:27 -0400 (Wed, 15 Jul 2009) | 2 lines #6076 Add a title to the IDLE Preferences window. ........ r74020 | georg.brandl | 2009-07-16 03:18:07 -0400 (Thu, 16 Jul 2009) | 1 line #5910: fix kqueue for calls with more than one event. ........ r74021 | georg.brandl | 2009-07-16 03:33:04 -0400 (Thu, 16 Jul 2009) | 1 line #6486: start with built in functions rather than "built in objects". ........ r74022 | georg.brandl | 2009-07-16 03:38:35 -0400 (Thu, 16 Jul 2009) | 1 line #6481: fix typo in os.system() replacement. ........ r74023 | jesse.noller | 2009-07-16 10:23:04 -0400 (Thu, 16 Jul 2009) | 1 line Issue 6433: multiprocessing.pool.map hangs on empty list ........
17 years ago
15 years ago
Merged revisions 78018,78035-78040,78042-78043,78046,78048-78052,78054,78059,78075-78080 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r78018 | georg.brandl | 2010-02-06 11:08:21 +0100 (Sa, 06 Feb 2010) | 1 line #7864: make deprecation notices a bit clearer. ........ r78035 | georg.brandl | 2010-02-06 23:44:17 +0100 (Sa, 06 Feb 2010) | 1 line Fix duplicate import. ........ r78036 | georg.brandl | 2010-02-06 23:49:47 +0100 (Sa, 06 Feb 2010) | 1 line Remove unused import. ........ r78037 | georg.brandl | 2010-02-06 23:59:15 +0100 (Sa, 06 Feb 2010) | 1 line No need to assign the results of expressions used only for side effects. ........ r78038 | georg.brandl | 2010-02-07 00:02:29 +0100 (So, 07 Feb 2010) | 1 line Add a missing import. ........ r78039 | georg.brandl | 2010-02-07 00:06:24 +0100 (So, 07 Feb 2010) | 1 line Add missing imports. ........ r78040 | georg.brandl | 2010-02-07 00:08:00 +0100 (So, 07 Feb 2010) | 1 line Fix a few UnboundLocalErrors in test_long. ........ r78042 | georg.brandl | 2010-02-07 00:12:12 +0100 (So, 07 Feb 2010) | 1 line Add missing import. ........ r78043 | georg.brandl | 2010-02-07 00:12:19 +0100 (So, 07 Feb 2010) | 1 line Remove duplicate test method. ........ r78046 | georg.brandl | 2010-02-07 00:18:00 +0100 (So, 07 Feb 2010) | 1 line Fix various missing import/unbound name errors. ........ r78048 | georg.brandl | 2010-02-07 00:23:45 +0100 (So, 07 Feb 2010) | 1 line We heard you like test failures so we put unbound locals in your test so that you can fail while you fail. ........ r78049 | georg.brandl | 2010-02-07 00:33:33 +0100 (So, 07 Feb 2010) | 1 line Fix import/access for some identifiers. _TestSharedCTypes does not seem to be executed? ........ r78050 | georg.brandl | 2010-02-07 00:34:10 +0100 (So, 07 Feb 2010) | 1 line Fix more unbound locals in code paths that do not seem to be used. ........ r78051 | georg.brandl | 2010-02-07 00:53:52 +0100 (So, 07 Feb 2010) | 1 line Add missing import when running these tests standalone. ........ r78052 | georg.brandl | 2010-02-07 00:54:04 +0100 (So, 07 Feb 2010) | 1 line Add missing import when running these tests standalone. ........ r78054 | georg.brandl | 2010-02-07 00:58:25 +0100 (So, 07 Feb 2010) | 1 line Add missing import. ........ r78059 | georg.brandl | 2010-02-07 12:34:15 +0100 (So, 07 Feb 2010) | 1 line Use "regexp" consistently. ........ r78075 | georg.brandl | 2010-02-07 13:16:12 +0100 (So, 07 Feb 2010) | 1 line Fix another duplicated test method. ........ r78076 | georg.brandl | 2010-02-07 13:19:43 +0100 (So, 07 Feb 2010) | 1 line Fix wrong usage of "except X, Y:". ........ r78077 | georg.brandl | 2010-02-07 13:25:50 +0100 (So, 07 Feb 2010) | 1 line Fix two redefined test methods. ........ r78078 | georg.brandl | 2010-02-07 13:27:06 +0100 (So, 07 Feb 2010) | 1 line Fix a redefined test method. ........ r78079 | georg.brandl | 2010-02-07 13:34:26 +0100 (So, 07 Feb 2010) | 1 line Add a minimal test for fnmatchcase(). ........ r78080 | georg.brandl | 2010-02-07 13:55:12 +0100 (So, 07 Feb 2010) | 1 line Remove duplicate test method. ........
16 years ago
Merged revisions 78018,78035-78040,78042-78043,78046,78048-78052,78054,78059,78075-78080 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r78018 | georg.brandl | 2010-02-06 11:08:21 +0100 (Sa, 06 Feb 2010) | 1 line #7864: make deprecation notices a bit clearer. ........ r78035 | georg.brandl | 2010-02-06 23:44:17 +0100 (Sa, 06 Feb 2010) | 1 line Fix duplicate import. ........ r78036 | georg.brandl | 2010-02-06 23:49:47 +0100 (Sa, 06 Feb 2010) | 1 line Remove unused import. ........ r78037 | georg.brandl | 2010-02-06 23:59:15 +0100 (Sa, 06 Feb 2010) | 1 line No need to assign the results of expressions used only for side effects. ........ r78038 | georg.brandl | 2010-02-07 00:02:29 +0100 (So, 07 Feb 2010) | 1 line Add a missing import. ........ r78039 | georg.brandl | 2010-02-07 00:06:24 +0100 (So, 07 Feb 2010) | 1 line Add missing imports. ........ r78040 | georg.brandl | 2010-02-07 00:08:00 +0100 (So, 07 Feb 2010) | 1 line Fix a few UnboundLocalErrors in test_long. ........ r78042 | georg.brandl | 2010-02-07 00:12:12 +0100 (So, 07 Feb 2010) | 1 line Add missing import. ........ r78043 | georg.brandl | 2010-02-07 00:12:19 +0100 (So, 07 Feb 2010) | 1 line Remove duplicate test method. ........ r78046 | georg.brandl | 2010-02-07 00:18:00 +0100 (So, 07 Feb 2010) | 1 line Fix various missing import/unbound name errors. ........ r78048 | georg.brandl | 2010-02-07 00:23:45 +0100 (So, 07 Feb 2010) | 1 line We heard you like test failures so we put unbound locals in your test so that you can fail while you fail. ........ r78049 | georg.brandl | 2010-02-07 00:33:33 +0100 (So, 07 Feb 2010) | 1 line Fix import/access for some identifiers. _TestSharedCTypes does not seem to be executed? ........ r78050 | georg.brandl | 2010-02-07 00:34:10 +0100 (So, 07 Feb 2010) | 1 line Fix more unbound locals in code paths that do not seem to be used. ........ r78051 | georg.brandl | 2010-02-07 00:53:52 +0100 (So, 07 Feb 2010) | 1 line Add missing import when running these tests standalone. ........ r78052 | georg.brandl | 2010-02-07 00:54:04 +0100 (So, 07 Feb 2010) | 1 line Add missing import when running these tests standalone. ........ r78054 | georg.brandl | 2010-02-07 00:58:25 +0100 (So, 07 Feb 2010) | 1 line Add missing import. ........ r78059 | georg.brandl | 2010-02-07 12:34:15 +0100 (So, 07 Feb 2010) | 1 line Use "regexp" consistently. ........ r78075 | georg.brandl | 2010-02-07 13:16:12 +0100 (So, 07 Feb 2010) | 1 line Fix another duplicated test method. ........ r78076 | georg.brandl | 2010-02-07 13:19:43 +0100 (So, 07 Feb 2010) | 1 line Fix wrong usage of "except X, Y:". ........ r78077 | georg.brandl | 2010-02-07 13:25:50 +0100 (So, 07 Feb 2010) | 1 line Fix two redefined test methods. ........ r78078 | georg.brandl | 2010-02-07 13:27:06 +0100 (So, 07 Feb 2010) | 1 line Fix a redefined test method. ........ r78079 | georg.brandl | 2010-02-07 13:34:26 +0100 (So, 07 Feb 2010) | 1 line Add a minimal test for fnmatchcase(). ........ r78080 | georg.brandl | 2010-02-07 13:55:12 +0100 (So, 07 Feb 2010) | 1 line Remove duplicate test method. ........
16 years ago
Merged revisions 70912,70944,70968,71033,71041,71208,71263,71286,71395-71396,71405-71406,71485,71492,71494 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r70912 | georg.brandl | 2009-03-31 17:35:46 -0500 (Tue, 31 Mar 2009) | 1 line #5617: add a handy function to print a unicode string to gdbinit. ........ r70944 | georg.brandl | 2009-03-31 23:32:39 -0500 (Tue, 31 Mar 2009) | 1 line #5631: add upload to list of possible commands, which is presented in --help-commands. ........ r70968 | michael.foord | 2009-04-01 13:25:38 -0500 (Wed, 01 Apr 2009) | 1 line Adding Wing project file ........ r71033 | brett.cannon | 2009-04-01 22:34:53 -0500 (Wed, 01 Apr 2009) | 3 lines Fix two issues introduced by issue #71031 by changing the signature of PyImport_AppendInittab() to take a const char *. ........ r71041 | jesse.noller | 2009-04-02 00:17:26 -0500 (Thu, 02 Apr 2009) | 1 line Add custom initializer argument to multiprocess.Manager*, courtesy of lekma ........ r71208 | michael.foord | 2009-04-04 20:15:01 -0500 (Sat, 04 Apr 2009) | 4 lines Change the way unittest.TestSuite use their tests to always access them through iteration. Non behavior changing, this allows you to create custom subclasses that override __iter__. Issue #5693 ........ r71263 | michael.foord | 2009-04-05 14:19:28 -0500 (Sun, 05 Apr 2009) | 4 lines Adding assertIs and assertIsNot methods to unittest.TestCase Issue #2578 ........ r71286 | tarek.ziade | 2009-04-05 17:04:38 -0500 (Sun, 05 Apr 2009) | 1 line added a simplest test to distutils.spawn._nt_quote_args ........ r71395 | benjamin.peterson | 2009-04-08 08:27:29 -0500 (Wed, 08 Apr 2009) | 1 line these must be installed to correctly run tests ........ r71396 | benjamin.peterson | 2009-04-08 08:29:41 -0500 (Wed, 08 Apr 2009) | 1 line fix syntax ........ r71405 | andrew.kuchling | 2009-04-09 06:22:47 -0500 (Thu, 09 Apr 2009) | 1 line Add items ........ r71406 | andrew.kuchling | 2009-04-09 06:23:36 -0500 (Thu, 09 Apr 2009) | 1 line Typo fixes ........ r71485 | andrew.kuchling | 2009-04-11 11:12:23 -0500 (Sat, 11 Apr 2009) | 1 line Add various items ........ r71492 | georg.brandl | 2009-04-11 13:19:27 -0500 (Sat, 11 Apr 2009) | 1 line Take credit for a patch of mine. ........ r71494 | benjamin.peterson | 2009-04-11 14:31:00 -0500 (Sat, 11 Apr 2009) | 1 line ignore py3_test_grammar when compiling the library ........
17 years ago
Merged revisions 70912,70944,70968,71033,71041,71208,71263,71286,71395-71396,71405-71406,71485,71492,71494 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r70912 | georg.brandl | 2009-03-31 17:35:46 -0500 (Tue, 31 Mar 2009) | 1 line #5617: add a handy function to print a unicode string to gdbinit. ........ r70944 | georg.brandl | 2009-03-31 23:32:39 -0500 (Tue, 31 Mar 2009) | 1 line #5631: add upload to list of possible commands, which is presented in --help-commands. ........ r70968 | michael.foord | 2009-04-01 13:25:38 -0500 (Wed, 01 Apr 2009) | 1 line Adding Wing project file ........ r71033 | brett.cannon | 2009-04-01 22:34:53 -0500 (Wed, 01 Apr 2009) | 3 lines Fix two issues introduced by issue #71031 by changing the signature of PyImport_AppendInittab() to take a const char *. ........ r71041 | jesse.noller | 2009-04-02 00:17:26 -0500 (Thu, 02 Apr 2009) | 1 line Add custom initializer argument to multiprocess.Manager*, courtesy of lekma ........ r71208 | michael.foord | 2009-04-04 20:15:01 -0500 (Sat, 04 Apr 2009) | 4 lines Change the way unittest.TestSuite use their tests to always access them through iteration. Non behavior changing, this allows you to create custom subclasses that override __iter__. Issue #5693 ........ r71263 | michael.foord | 2009-04-05 14:19:28 -0500 (Sun, 05 Apr 2009) | 4 lines Adding assertIs and assertIsNot methods to unittest.TestCase Issue #2578 ........ r71286 | tarek.ziade | 2009-04-05 17:04:38 -0500 (Sun, 05 Apr 2009) | 1 line added a simplest test to distutils.spawn._nt_quote_args ........ r71395 | benjamin.peterson | 2009-04-08 08:27:29 -0500 (Wed, 08 Apr 2009) | 1 line these must be installed to correctly run tests ........ r71396 | benjamin.peterson | 2009-04-08 08:29:41 -0500 (Wed, 08 Apr 2009) | 1 line fix syntax ........ r71405 | andrew.kuchling | 2009-04-09 06:22:47 -0500 (Thu, 09 Apr 2009) | 1 line Add items ........ r71406 | andrew.kuchling | 2009-04-09 06:23:36 -0500 (Thu, 09 Apr 2009) | 1 line Typo fixes ........ r71485 | andrew.kuchling | 2009-04-11 11:12:23 -0500 (Sat, 11 Apr 2009) | 1 line Add various items ........ r71492 | georg.brandl | 2009-04-11 13:19:27 -0500 (Sat, 11 Apr 2009) | 1 line Take credit for a patch of mine. ........ r71494 | benjamin.peterson | 2009-04-11 14:31:00 -0500 (Sat, 11 Apr 2009) | 1 line ignore py3_test_grammar when compiling the library ........
17 years ago
Merged revisions 70912,70944,70968,71033,71041,71208,71263,71286,71395-71396,71405-71406,71485,71492,71494 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r70912 | georg.brandl | 2009-03-31 17:35:46 -0500 (Tue, 31 Mar 2009) | 1 line #5617: add a handy function to print a unicode string to gdbinit. ........ r70944 | georg.brandl | 2009-03-31 23:32:39 -0500 (Tue, 31 Mar 2009) | 1 line #5631: add upload to list of possible commands, which is presented in --help-commands. ........ r70968 | michael.foord | 2009-04-01 13:25:38 -0500 (Wed, 01 Apr 2009) | 1 line Adding Wing project file ........ r71033 | brett.cannon | 2009-04-01 22:34:53 -0500 (Wed, 01 Apr 2009) | 3 lines Fix two issues introduced by issue #71031 by changing the signature of PyImport_AppendInittab() to take a const char *. ........ r71041 | jesse.noller | 2009-04-02 00:17:26 -0500 (Thu, 02 Apr 2009) | 1 line Add custom initializer argument to multiprocess.Manager*, courtesy of lekma ........ r71208 | michael.foord | 2009-04-04 20:15:01 -0500 (Sat, 04 Apr 2009) | 4 lines Change the way unittest.TestSuite use their tests to always access them through iteration. Non behavior changing, this allows you to create custom subclasses that override __iter__. Issue #5693 ........ r71263 | michael.foord | 2009-04-05 14:19:28 -0500 (Sun, 05 Apr 2009) | 4 lines Adding assertIs and assertIsNot methods to unittest.TestCase Issue #2578 ........ r71286 | tarek.ziade | 2009-04-05 17:04:38 -0500 (Sun, 05 Apr 2009) | 1 line added a simplest test to distutils.spawn._nt_quote_args ........ r71395 | benjamin.peterson | 2009-04-08 08:27:29 -0500 (Wed, 08 Apr 2009) | 1 line these must be installed to correctly run tests ........ r71396 | benjamin.peterson | 2009-04-08 08:29:41 -0500 (Wed, 08 Apr 2009) | 1 line fix syntax ........ r71405 | andrew.kuchling | 2009-04-09 06:22:47 -0500 (Thu, 09 Apr 2009) | 1 line Add items ........ r71406 | andrew.kuchling | 2009-04-09 06:23:36 -0500 (Thu, 09 Apr 2009) | 1 line Typo fixes ........ r71485 | andrew.kuchling | 2009-04-11 11:12:23 -0500 (Sat, 11 Apr 2009) | 1 line Add various items ........ r71492 | georg.brandl | 2009-04-11 13:19:27 -0500 (Sat, 11 Apr 2009) | 1 line Take credit for a patch of mine. ........ r71494 | benjamin.peterson | 2009-04-11 14:31:00 -0500 (Sat, 11 Apr 2009) | 1 line ignore py3_test_grammar when compiling the library ........
17 years ago
  1. #!/usr/bin/env python3
  2. #
  3. # Unit tests for the multiprocessing package
  4. #
  5. import unittest
  6. import queue as pyqueue
  7. import time
  8. import io
  9. import itertools
  10. import sys
  11. import os
  12. import gc
  13. import errno
  14. import signal
  15. import array
  16. import socket
  17. import random
  18. import logging
  19. import struct
  20. import operator
  21. import test.support
  22. import test.script_helper
  23. # Skip tests if _multiprocessing wasn't built.
  24. _multiprocessing = test.support.import_module('_multiprocessing')
  25. # Skip tests if sem_open implementation is broken.
  26. test.support.import_module('multiprocessing.synchronize')
  27. # import threading after _multiprocessing to raise a more revelant error
  28. # message: "No module named _multiprocessing". _multiprocessing is not compiled
  29. # without thread support.
  30. import threading
  31. import multiprocessing.dummy
  32. import multiprocessing.connection
  33. import multiprocessing.managers
  34. import multiprocessing.heap
  35. import multiprocessing.pool
  36. from multiprocessing import util
  37. try:
  38. from multiprocessing import reduction
  39. HAS_REDUCTION = reduction.HAVE_SEND_HANDLE
  40. except ImportError:
  41. HAS_REDUCTION = False
  42. try:
  43. from multiprocessing.sharedctypes import Value, copy
  44. HAS_SHAREDCTYPES = True
  45. except ImportError:
  46. HAS_SHAREDCTYPES = False
  47. try:
  48. import msvcrt
  49. except ImportError:
  50. msvcrt = None
  51. #
  52. #
  53. #
  54. def latin(s):
  55. return s.encode('latin')
  56. #
  57. # Constants
  58. #
  59. LOG_LEVEL = util.SUBWARNING
  60. #LOG_LEVEL = logging.DEBUG
  61. DELTA = 0.1
  62. CHECK_TIMINGS = False # making true makes tests take a lot longer
  63. # and can sometimes cause some non-serious
  64. # failures because some calls block a bit
  65. # longer than expected
  66. if CHECK_TIMINGS:
  67. TIMEOUT1, TIMEOUT2, TIMEOUT3 = 0.82, 0.35, 1.4
  68. else:
  69. TIMEOUT1, TIMEOUT2, TIMEOUT3 = 0.1, 0.1, 0.1
  70. HAVE_GETVALUE = not getattr(_multiprocessing,
  71. 'HAVE_BROKEN_SEM_GETVALUE', False)
  72. WIN32 = (sys.platform == "win32")
  73. from multiprocessing.connection import wait
  74. def wait_for_handle(handle, timeout):
  75. if timeout is not None and timeout < 0.0:
  76. timeout = None
  77. return wait([handle], timeout)
  78. try:
  79. MAXFD = os.sysconf("SC_OPEN_MAX")
  80. except:
  81. MAXFD = 256
  82. # To speed up tests when using the forkserver, we can preload these:
  83. PRELOAD = ['__main__', 'test.test_multiprocessing_forkserver']
  84. #
  85. # Some tests require ctypes
  86. #
  87. try:
  88. from ctypes import Structure, c_int, c_double
  89. except ImportError:
  90. Structure = object
  91. c_int = c_double = None
  92. def check_enough_semaphores():
  93. """Check that the system supports enough semaphores to run the test."""
  94. # minimum number of semaphores available according to POSIX
  95. nsems_min = 256
  96. try:
  97. nsems = os.sysconf("SC_SEM_NSEMS_MAX")
  98. except (AttributeError, ValueError):
  99. # sysconf not available or setting not available
  100. return
  101. if nsems == -1 or nsems >= nsems_min:
  102. return
  103. raise unittest.SkipTest("The OS doesn't support enough semaphores "
  104. "to run the test (required: %d)." % nsems_min)
  105. #
  106. # Creates a wrapper for a function which records the time it takes to finish
  107. #
  108. class TimingWrapper(object):
  109. def __init__(self, func):
  110. self.func = func
  111. self.elapsed = None
  112. def __call__(self, *args, **kwds):
  113. t = time.time()
  114. try:
  115. return self.func(*args, **kwds)
  116. finally:
  117. self.elapsed = time.time() - t
  118. #
  119. # Base class for test cases
  120. #
  121. class BaseTestCase(object):
  122. ALLOWED_TYPES = ('processes', 'manager', 'threads')
  123. def assertTimingAlmostEqual(self, a, b):
  124. if CHECK_TIMINGS:
  125. self.assertAlmostEqual(a, b, 1)
  126. def assertReturnsIfImplemented(self, value, func, *args):
  127. try:
  128. res = func(*args)
  129. except NotImplementedError:
  130. pass
  131. else:
  132. return self.assertEqual(value, res)
  133. # For the sanity of Windows users, rather than crashing or freezing in
  134. # multiple ways.
  135. def __reduce__(self, *args):
  136. raise NotImplementedError("shouldn't try to pickle a test case")
  137. __reduce_ex__ = __reduce__
  138. #
  139. # Return the value of a semaphore
  140. #
  141. def get_value(self):
  142. try:
  143. return self.get_value()
  144. except AttributeError:
  145. try:
  146. return self._Semaphore__value
  147. except AttributeError:
  148. try:
  149. return self._value
  150. except AttributeError:
  151. raise NotImplementedError
  152. #
  153. # Testcases
  154. #
  155. class _TestProcess(BaseTestCase):
  156. ALLOWED_TYPES = ('processes', 'threads')
  157. def test_current(self):
  158. if self.TYPE == 'threads':
  159. self.skipTest('test not appropriate for {}'.format(self.TYPE))
  160. current = self.current_process()
  161. authkey = current.authkey
  162. self.assertTrue(current.is_alive())
  163. self.assertTrue(not current.daemon)
  164. self.assertIsInstance(authkey, bytes)
  165. self.assertTrue(len(authkey) > 0)
  166. self.assertEqual(current.ident, os.getpid())
  167. self.assertEqual(current.exitcode, None)
  168. def test_daemon_argument(self):
  169. if self.TYPE == "threads":
  170. self.skipTest('test not appropriate for {}'.format(self.TYPE))
  171. # By default uses the current process's daemon flag.
  172. proc0 = self.Process(target=self._test)
  173. self.assertEqual(proc0.daemon, self.current_process().daemon)
  174. proc1 = self.Process(target=self._test, daemon=True)
  175. self.assertTrue(proc1.daemon)
  176. proc2 = self.Process(target=self._test, daemon=False)
  177. self.assertFalse(proc2.daemon)
  178. @classmethod
  179. def _test(cls, q, *args, **kwds):
  180. current = cls.current_process()
  181. q.put(args)
  182. q.put(kwds)
  183. q.put(current.name)
  184. if cls.TYPE != 'threads':
  185. q.put(bytes(current.authkey))
  186. q.put(current.pid)
  187. def test_process(self):
  188. q = self.Queue(1)
  189. e = self.Event()
  190. args = (q, 1, 2)
  191. kwargs = {'hello':23, 'bye':2.54}
  192. name = 'SomeProcess'
  193. p = self.Process(
  194. target=self._test, args=args, kwargs=kwargs, name=name
  195. )
  196. p.daemon = True
  197. current = self.current_process()
  198. if self.TYPE != 'threads':
  199. self.assertEqual(p.authkey, current.authkey)
  200. self.assertEqual(p.is_alive(), False)
  201. self.assertEqual(p.daemon, True)
  202. self.assertNotIn(p, self.active_children())
  203. self.assertTrue(type(self.active_children()) is list)
  204. self.assertEqual(p.exitcode, None)
  205. p.start()
  206. self.assertEqual(p.exitcode, None)
  207. self.assertEqual(p.is_alive(), True)
  208. self.assertIn(p, self.active_children())
  209. self.assertEqual(q.get(), args[1:])
  210. self.assertEqual(q.get(), kwargs)
  211. self.assertEqual(q.get(), p.name)
  212. if self.TYPE != 'threads':
  213. self.assertEqual(q.get(), current.authkey)
  214. self.assertEqual(q.get(), p.pid)
  215. p.join()
  216. self.assertEqual(p.exitcode, 0)
  217. self.assertEqual(p.is_alive(), False)
  218. self.assertNotIn(p, self.active_children())
  219. @classmethod
  220. def _test_terminate(cls):
  221. time.sleep(100)
  222. def test_terminate(self):
  223. if self.TYPE == 'threads':
  224. self.skipTest('test not appropriate for {}'.format(self.TYPE))
  225. p = self.Process(target=self._test_terminate)
  226. p.daemon = True
  227. p.start()
  228. self.assertEqual(p.is_alive(), True)
  229. self.assertIn(p, self.active_children())
  230. self.assertEqual(p.exitcode, None)
  231. join = TimingWrapper(p.join)
  232. self.assertEqual(join(0), None)
  233. self.assertTimingAlmostEqual(join.elapsed, 0.0)
  234. self.assertEqual(p.is_alive(), True)
  235. self.assertEqual(join(-1), None)
  236. self.assertTimingAlmostEqual(join.elapsed, 0.0)
  237. self.assertEqual(p.is_alive(), True)
  238. # XXX maybe terminating too soon causes the problems on Gentoo...
  239. time.sleep(1)
  240. p.terminate()
  241. if hasattr(signal, 'alarm'):
  242. # On the Gentoo buildbot waitpid() often seems to block forever.
  243. # We use alarm() to interrupt it if it blocks for too long.
  244. def handler(*args):
  245. raise RuntimeError('join took too long: %s' % p)
  246. old_handler = signal.signal(signal.SIGALRM, handler)
  247. try:
  248. signal.alarm(10)
  249. self.assertEqual(join(), None)
  250. finally:
  251. signal.alarm(0)
  252. signal.signal(signal.SIGALRM, old_handler)
  253. else:
  254. self.assertEqual(join(), None)
  255. self.assertTimingAlmostEqual(join.elapsed, 0.0)
  256. self.assertEqual(p.is_alive(), False)
  257. self.assertNotIn(p, self.active_children())
  258. p.join()
  259. # XXX sometimes get p.exitcode == 0 on Windows ...
  260. #self.assertEqual(p.exitcode, -signal.SIGTERM)
  261. def test_cpu_count(self):
  262. try:
  263. cpus = multiprocessing.cpu_count()
  264. except NotImplementedError:
  265. cpus = 1
  266. self.assertTrue(type(cpus) is int)
  267. self.assertTrue(cpus >= 1)
  268. def test_active_children(self):
  269. self.assertEqual(type(self.active_children()), list)
  270. p = self.Process(target=time.sleep, args=(DELTA,))
  271. self.assertNotIn(p, self.active_children())
  272. p.daemon = True
  273. p.start()
  274. self.assertIn(p, self.active_children())
  275. p.join()
  276. self.assertNotIn(p, self.active_children())
  277. @classmethod
  278. def _test_recursion(cls, wconn, id):
  279. wconn.send(id)
  280. if len(id) < 2:
  281. for i in range(2):
  282. p = cls.Process(
  283. target=cls._test_recursion, args=(wconn, id+[i])
  284. )
  285. p.start()
  286. p.join()
  287. def test_recursion(self):
  288. rconn, wconn = self.Pipe(duplex=False)
  289. self._test_recursion(wconn, [])
  290. time.sleep(DELTA)
  291. result = []
  292. while rconn.poll():
  293. result.append(rconn.recv())
  294. expected = [
  295. [],
  296. [0],
  297. [0, 0],
  298. [0, 1],
  299. [1],
  300. [1, 0],
  301. [1, 1]
  302. ]
  303. self.assertEqual(result, expected)
  304. @classmethod
  305. def _test_sentinel(cls, event):
  306. event.wait(10.0)
  307. def test_sentinel(self):
  308. if self.TYPE == "threads":
  309. self.skipTest('test not appropriate for {}'.format(self.TYPE))
  310. event = self.Event()
  311. p = self.Process(target=self._test_sentinel, args=(event,))
  312. with self.assertRaises(ValueError):
  313. p.sentinel
  314. p.start()
  315. self.addCleanup(p.join)
  316. sentinel = p.sentinel
  317. self.assertIsInstance(sentinel, int)
  318. self.assertFalse(wait_for_handle(sentinel, timeout=0.0))
  319. event.set()
  320. p.join()
  321. self.assertTrue(wait_for_handle(sentinel, timeout=1))
  322. #
  323. #
  324. #
  325. class _UpperCaser(multiprocessing.Process):
  326. def __init__(self):
  327. multiprocessing.Process.__init__(self)
  328. self.child_conn, self.parent_conn = multiprocessing.Pipe()
  329. def run(self):
  330. self.parent_conn.close()
  331. for s in iter(self.child_conn.recv, None):
  332. self.child_conn.send(s.upper())
  333. self.child_conn.close()
  334. def submit(self, s):
  335. assert type(s) is str
  336. self.parent_conn.send(s)
  337. return self.parent_conn.recv()
  338. def stop(self):
  339. self.parent_conn.send(None)
  340. self.parent_conn.close()
  341. self.child_conn.close()
  342. class _TestSubclassingProcess(BaseTestCase):
  343. ALLOWED_TYPES = ('processes',)
  344. def test_subclassing(self):
  345. uppercaser = _UpperCaser()
  346. uppercaser.daemon = True
  347. uppercaser.start()
  348. self.assertEqual(uppercaser.submit('hello'), 'HELLO')
  349. self.assertEqual(uppercaser.submit('world'), 'WORLD')
  350. uppercaser.stop()
  351. uppercaser.join()
  352. def test_stderr_flush(self):
  353. # sys.stderr is flushed at process shutdown (issue #13812)
  354. if self.TYPE == "threads":
  355. self.skipTest('test not appropriate for {}'.format(self.TYPE))
  356. testfn = test.support.TESTFN
  357. self.addCleanup(test.support.unlink, testfn)
  358. proc = self.Process(target=self._test_stderr_flush, args=(testfn,))
  359. proc.start()
  360. proc.join()
  361. with open(testfn, 'r') as f:
  362. err = f.read()
  363. # The whole traceback was printed
  364. self.assertIn("ZeroDivisionError", err)
  365. self.assertIn("test_multiprocessing.py", err)
  366. self.assertIn("1/0 # MARKER", err)
  367. @classmethod
  368. def _test_stderr_flush(cls, testfn):
  369. sys.stderr = open(testfn, 'w')
  370. 1/0 # MARKER
  371. @classmethod
  372. def _test_sys_exit(cls, reason, testfn):
  373. sys.stderr = open(testfn, 'w')
  374. sys.exit(reason)
  375. def test_sys_exit(self):
  376. # See Issue 13854
  377. if self.TYPE == 'threads':
  378. self.skipTest('test not appropriate for {}'.format(self.TYPE))
  379. testfn = test.support.TESTFN
  380. self.addCleanup(test.support.unlink, testfn)
  381. for reason, code in (([1, 2, 3], 1), ('ignore this', 1)):
  382. p = self.Process(target=self._test_sys_exit, args=(reason, testfn))
  383. p.daemon = True
  384. p.start()
  385. p.join(5)
  386. self.assertEqual(p.exitcode, code)
  387. with open(testfn, 'r') as f:
  388. self.assertEqual(f.read().rstrip(), str(reason))
  389. for reason in (True, False, 8):
  390. p = self.Process(target=sys.exit, args=(reason,))
  391. p.daemon = True
  392. p.start()
  393. p.join(5)
  394. self.assertEqual(p.exitcode, reason)
  395. #
  396. #
  397. #
  398. def queue_empty(q):
  399. if hasattr(q, 'empty'):
  400. return q.empty()
  401. else:
  402. return q.qsize() == 0
  403. def queue_full(q, maxsize):
  404. if hasattr(q, 'full'):
  405. return q.full()
  406. else:
  407. return q.qsize() == maxsize
  408. class _TestQueue(BaseTestCase):
  409. @classmethod
  410. def _test_put(cls, queue, child_can_start, parent_can_continue):
  411. child_can_start.wait()
  412. for i in range(6):
  413. queue.get()
  414. parent_can_continue.set()
  415. def test_put(self):
  416. MAXSIZE = 6
  417. queue = self.Queue(maxsize=MAXSIZE)
  418. child_can_start = self.Event()
  419. parent_can_continue = self.Event()
  420. proc = self.Process(
  421. target=self._test_put,
  422. args=(queue, child_can_start, parent_can_continue)
  423. )
  424. proc.daemon = True
  425. proc.start()
  426. self.assertEqual(queue_empty(queue), True)
  427. self.assertEqual(queue_full(queue, MAXSIZE), False)
  428. queue.put(1)
  429. queue.put(2, True)
  430. queue.put(3, True, None)
  431. queue.put(4, False)
  432. queue.put(5, False, None)
  433. queue.put_nowait(6)
  434. # the values may be in buffer but not yet in pipe so sleep a bit
  435. time.sleep(DELTA)
  436. self.assertEqual(queue_empty(queue), False)
  437. self.assertEqual(queue_full(queue, MAXSIZE), True)
  438. put = TimingWrapper(queue.put)
  439. put_nowait = TimingWrapper(queue.put_nowait)
  440. self.assertRaises(pyqueue.Full, put, 7, False)
  441. self.assertTimingAlmostEqual(put.elapsed, 0)
  442. self.assertRaises(pyqueue.Full, put, 7, False, None)
  443. self.assertTimingAlmostEqual(put.elapsed, 0)
  444. self.assertRaises(pyqueue.Full, put_nowait, 7)
  445. self.assertTimingAlmostEqual(put_nowait.elapsed, 0)
  446. self.assertRaises(pyqueue.Full, put, 7, True, TIMEOUT1)
  447. self.assertTimingAlmostEqual(put.elapsed, TIMEOUT1)
  448. self.assertRaises(pyqueue.Full, put, 7, False, TIMEOUT2)
  449. self.assertTimingAlmostEqual(put.elapsed, 0)
  450. self.assertRaises(pyqueue.Full, put, 7, True, timeout=TIMEOUT3)
  451. self.assertTimingAlmostEqual(put.elapsed, TIMEOUT3)
  452. child_can_start.set()
  453. parent_can_continue.wait()
  454. self.assertEqual(queue_empty(queue), True)
  455. self.assertEqual(queue_full(queue, MAXSIZE), False)
  456. proc.join()
  457. @classmethod
  458. def _test_get(cls, queue, child_can_start, parent_can_continue):
  459. child_can_start.wait()
  460. #queue.put(1)
  461. queue.put(2)
  462. queue.put(3)
  463. queue.put(4)
  464. queue.put(5)
  465. parent_can_continue.set()
  466. def test_get(self):
  467. queue = self.Queue()
  468. child_can_start = self.Event()
  469. parent_can_continue = self.Event()
  470. proc = self.Process(
  471. target=self._test_get,
  472. args=(queue, child_can_start, parent_can_continue)
  473. )
  474. proc.daemon = True
  475. proc.start()
  476. self.assertEqual(queue_empty(queue), True)
  477. child_can_start.set()
  478. parent_can_continue.wait()
  479. time.sleep(DELTA)
  480. self.assertEqual(queue_empty(queue), False)
  481. # Hangs unexpectedly, remove for now
  482. #self.assertEqual(queue.get(), 1)
  483. self.assertEqual(queue.get(True, None), 2)
  484. self.assertEqual(queue.get(True), 3)
  485. self.assertEqual(queue.get(timeout=1), 4)
  486. self.assertEqual(queue.get_nowait(), 5)
  487. self.assertEqual(queue_empty(queue), True)
  488. get = TimingWrapper(queue.get)
  489. get_nowait = TimingWrapper(queue.get_nowait)
  490. self.assertRaises(pyqueue.Empty, get, False)
  491. self.assertTimingAlmostEqual(get.elapsed, 0)
  492. self.assertRaises(pyqueue.Empty, get, False, None)
  493. self.assertTimingAlmostEqual(get.elapsed, 0)
  494. self.assertRaises(pyqueue.Empty, get_nowait)
  495. self.assertTimingAlmostEqual(get_nowait.elapsed, 0)
  496. self.assertRaises(pyqueue.Empty, get, True, TIMEOUT1)
  497. self.assertTimingAlmostEqual(get.elapsed, TIMEOUT1)
  498. self.assertRaises(pyqueue.Empty, get, False, TIMEOUT2)
  499. self.assertTimingAlmostEqual(get.elapsed, 0)
  500. self.assertRaises(pyqueue.Empty, get, timeout=TIMEOUT3)
  501. self.assertTimingAlmostEqual(get.elapsed, TIMEOUT3)
  502. proc.join()
  503. @classmethod
  504. def _test_fork(cls, queue):
  505. for i in range(10, 20):
  506. queue.put(i)
  507. # note that at this point the items may only be buffered, so the
  508. # process cannot shutdown until the feeder thread has finished
  509. # pushing items onto the pipe.
  510. def test_fork(self):
  511. # Old versions of Queue would fail to create a new feeder
  512. # thread for a forked process if the original process had its
  513. # own feeder thread. This test checks that this no longer
  514. # happens.
  515. queue = self.Queue()
  516. # put items on queue so that main process starts a feeder thread
  517. for i in range(10):
  518. queue.put(i)
  519. # wait to make sure thread starts before we fork a new process
  520. time.sleep(DELTA)
  521. # fork process
  522. p = self.Process(target=self._test_fork, args=(queue,))
  523. p.daemon = True
  524. p.start()
  525. # check that all expected items are in the queue
  526. for i in range(20):
  527. self.assertEqual(queue.get(), i)
  528. self.assertRaises(pyqueue.Empty, queue.get, False)
  529. p.join()
  530. def test_qsize(self):
  531. q = self.Queue()
  532. try:
  533. self.assertEqual(q.qsize(), 0)
  534. except NotImplementedError:
  535. self.skipTest('qsize method not implemented')
  536. q.put(1)
  537. self.assertEqual(q.qsize(), 1)
  538. q.put(5)
  539. self.assertEqual(q.qsize(), 2)
  540. q.get()
  541. self.assertEqual(q.qsize(), 1)
  542. q.get()
  543. self.assertEqual(q.qsize(), 0)
  544. @classmethod
  545. def _test_task_done(cls, q):
  546. for obj in iter(q.get, None):
  547. time.sleep(DELTA)
  548. q.task_done()
  549. def test_task_done(self):
  550. queue = self.JoinableQueue()
  551. if sys.version_info < (2, 5) and not hasattr(queue, 'task_done'):
  552. self.skipTest("requires 'queue.task_done()' method")
  553. workers = [self.Process(target=self._test_task_done, args=(queue,))
  554. for i in range(4)]
  555. for p in workers:
  556. p.daemon = True
  557. p.start()
  558. for i in range(10):
  559. queue.put(i)
  560. queue.join()
  561. for p in workers:
  562. queue.put(None)
  563. for p in workers:
  564. p.join()
  565. def test_timeout(self):
  566. q = multiprocessing.Queue()
  567. start = time.time()
  568. self.assertRaises(pyqueue.Empty, q.get, True, 0.2)
  569. delta = time.time() - start
  570. self.assertGreaterEqual(delta, 0.18)
  571. #
  572. #
  573. #
  574. class _TestLock(BaseTestCase):
  575. def test_lock(self):
  576. lock = self.Lock()
  577. self.assertEqual(lock.acquire(), True)
  578. self.assertEqual(lock.acquire(False), False)
  579. self.assertEqual(lock.release(), None)
  580. self.assertRaises((ValueError, threading.ThreadError), lock.release)
  581. def test_rlock(self):
  582. lock = self.RLock()
  583. self.assertEqual(lock.acquire(), True)
  584. self.assertEqual(lock.acquire(), True)
  585. self.assertEqual(lock.acquire(), True)
  586. self.assertEqual(lock.release(), None)
  587. self.assertEqual(lock.release(), None)
  588. self.assertEqual(lock.release(), None)
  589. self.assertRaises((AssertionError, RuntimeError), lock.release)
  590. def test_lock_context(self):
  591. with self.Lock():
  592. pass
  593. class _TestSemaphore(BaseTestCase):
  594. def _test_semaphore(self, sem):
  595. self.assertReturnsIfImplemented(2, get_value, sem)
  596. self.assertEqual(sem.acquire(), True)
  597. self.assertReturnsIfImplemented(1, get_value, sem)
  598. self.assertEqual(sem.acquire(), True)
  599. self.assertReturnsIfImplemented(0, get_value, sem)
  600. self.assertEqual(sem.acquire(False), False)
  601. self.assertReturnsIfImplemented(0, get_value, sem)
  602. self.assertEqual(sem.release(), None)
  603. self.assertReturnsIfImplemented(1, get_value, sem)
  604. self.assertEqual(sem.release(), None)
  605. self.assertReturnsIfImplemented(2, get_value, sem)
  606. def test_semaphore(self):
  607. sem = self.Semaphore(2)
  608. self._test_semaphore(sem)
  609. self.assertEqual(sem.release(), None)
  610. self.assertReturnsIfImplemented(3, get_value, sem)
  611. self.assertEqual(sem.release(), None)
  612. self.assertReturnsIfImplemented(4, get_value, sem)
  613. def test_bounded_semaphore(self):
  614. sem = self.BoundedSemaphore(2)
  615. self._test_semaphore(sem)
  616. # Currently fails on OS/X
  617. #if HAVE_GETVALUE:
  618. # self.assertRaises(ValueError, sem.release)
  619. # self.assertReturnsIfImplemented(2, get_value, sem)
  620. def test_timeout(self):
  621. if self.TYPE != 'processes':
  622. self.skipTest('test not appropriate for {}'.format(self.TYPE))
  623. sem = self.Semaphore(0)
  624. acquire = TimingWrapper(sem.acquire)
  625. self.assertEqual(acquire(False), False)
  626. self.assertTimingAlmostEqual(acquire.elapsed, 0.0)
  627. self.assertEqual(acquire(False, None), False)
  628. self.assertTimingAlmostEqual(acquire.elapsed, 0.0)
  629. self.assertEqual(acquire(False, TIMEOUT1), False)
  630. self.assertTimingAlmostEqual(acquire.elapsed, 0)
  631. self.assertEqual(acquire(True, TIMEOUT2), False)
  632. self.assertTimingAlmostEqual(acquire.elapsed, TIMEOUT2)
  633. self.assertEqual(acquire(timeout=TIMEOUT3), False)
  634. self.assertTimingAlmostEqual(acquire.elapsed, TIMEOUT3)
  635. class _TestCondition(BaseTestCase):
  636. @classmethod
  637. def f(cls, cond, sleeping, woken, timeout=None):
  638. cond.acquire()
  639. sleeping.release()
  640. cond.wait(timeout)
  641. woken.release()
  642. cond.release()
  643. def check_invariant(self, cond):
  644. # this is only supposed to succeed when there are no sleepers
  645. if self.TYPE == 'processes':
  646. try:
  647. sleepers = (cond._sleeping_count.get_value() -
  648. cond._woken_count.get_value())
  649. self.assertEqual(sleepers, 0)
  650. self.assertEqual(cond._wait_semaphore.get_value(), 0)
  651. except NotImplementedError:
  652. pass
  653. def test_notify(self):
  654. cond = self.Condition()
  655. sleeping = self.Semaphore(0)
  656. woken = self.Semaphore(0)
  657. p = self.Process(target=self.f, args=(cond, sleeping, woken))
  658. p.daemon = True
  659. p.start()
  660. p = threading.Thread(target=self.f, args=(cond, sleeping, woken))
  661. p.daemon = True
  662. p.start()
  663. # wait for both children to start sleeping
  664. sleeping.acquire()
  665. sleeping.acquire()
  666. # check no process/thread has woken up
  667. time.sleep(DELTA)
  668. self.assertReturnsIfImplemented(0, get_value, woken)
  669. # wake up one process/thread
  670. cond.acquire()
  671. cond.notify()
  672. cond.release()
  673. # check one process/thread has woken up
  674. time.sleep(DELTA)
  675. self.assertReturnsIfImplemented(1, get_value, woken)
  676. # wake up another
  677. cond.acquire()
  678. cond.notify()
  679. cond.release()
  680. # check other has woken up
  681. time.sleep(DELTA)
  682. self.assertReturnsIfImplemented(2, get_value, woken)
  683. # check state is not mucked up
  684. self.check_invariant(cond)
  685. p.join()
  686. def test_notify_all(self):
  687. cond = self.Condition()
  688. sleeping = self.Semaphore(0)
  689. woken = self.Semaphore(0)
  690. # start some threads/processes which will timeout
  691. for i in range(3):
  692. p = self.Process(target=self.f,
  693. args=(cond, sleeping, woken, TIMEOUT1))
  694. p.daemon = True
  695. p.start()
  696. t = threading.Thread(target=self.f,
  697. args=(cond, sleeping, woken, TIMEOUT1))
  698. t.daemon = True
  699. t.start()
  700. # wait for them all to sleep
  701. for i in range(6):
  702. sleeping.acquire()
  703. # check they have all timed out
  704. for i in range(6):
  705. woken.acquire()
  706. self.assertReturnsIfImplemented(0, get_value, woken)
  707. # check state is not mucked up
  708. self.check_invariant(cond)
  709. # start some more threads/processes
  710. for i in range(3):
  711. p = self.Process(target=self.f, args=(cond, sleeping, woken))
  712. p.daemon = True
  713. p.start()
  714. t = threading.Thread(target=self.f, args=(cond, sleeping, woken))
  715. t.daemon = True
  716. t.start()
  717. # wait for them to all sleep
  718. for i in range(6):
  719. sleeping.acquire()
  720. # check no process/thread has woken up
  721. time.sleep(DELTA)
  722. self.assertReturnsIfImplemented(0, get_value, woken)
  723. # wake them all up
  724. cond.acquire()
  725. cond.notify_all()
  726. cond.release()
  727. # check they have all woken
  728. for i in range(10):
  729. try:
  730. if get_value(woken) == 6:
  731. break
  732. except NotImplementedError:
  733. break
  734. time.sleep(DELTA)
  735. self.assertReturnsIfImplemented(6, get_value, woken)
  736. # check state is not mucked up
  737. self.check_invariant(cond)
  738. def test_timeout(self):
  739. cond = self.Condition()
  740. wait = TimingWrapper(cond.wait)
  741. cond.acquire()
  742. res = wait(TIMEOUT1)
  743. cond.release()
  744. self.assertEqual(res, False)
  745. self.assertTimingAlmostEqual(wait.elapsed, TIMEOUT1)
  746. @classmethod
  747. def _test_waitfor_f(cls, cond, state):
  748. with cond:
  749. state.value = 0
  750. cond.notify()
  751. result = cond.wait_for(lambda : state.value==4)
  752. if not result or state.value != 4:
  753. sys.exit(1)
  754. @unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes')
  755. def test_waitfor(self):
  756. # based on test in test/lock_tests.py
  757. cond = self.Condition()
  758. state = self.Value('i', -1)
  759. p = self.Process(target=self._test_waitfor_f, args=(cond, state))
  760. p.daemon = True
  761. p.start()
  762. with cond:
  763. result = cond.wait_for(lambda : state.value==0)
  764. self.assertTrue(result)
  765. self.assertEqual(state.value, 0)
  766. for i in range(4):
  767. time.sleep(0.01)
  768. with cond:
  769. state.value += 1
  770. cond.notify()
  771. p.join(5)
  772. self.assertFalse(p.is_alive())
  773. self.assertEqual(p.exitcode, 0)
  774. @classmethod
  775. def _test_waitfor_timeout_f(cls, cond, state, success, sem):
  776. sem.release()
  777. with cond:
  778. expected = 0.1
  779. dt = time.time()
  780. result = cond.wait_for(lambda : state.value==4, timeout=expected)
  781. dt = time.time() - dt
  782. # borrow logic in assertTimeout() from test/lock_tests.py
  783. if not result and expected * 0.6 < dt < expected * 10.0:
  784. success.value = True
  785. @unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes')
  786. def test_waitfor_timeout(self):
  787. # based on test in test/lock_tests.py
  788. cond = self.Condition()
  789. state = self.Value('i', 0)
  790. success = self.Value('i', False)
  791. sem = self.Semaphore(0)
  792. p = self.Process(target=self._test_waitfor_timeout_f,
  793. args=(cond, state, success, sem))
  794. p.daemon = True
  795. p.start()
  796. self.assertTrue(sem.acquire(timeout=10))
  797. # Only increment 3 times, so state == 4 is never reached.
  798. for i in range(3):
  799. time.sleep(0.01)
  800. with cond:
  801. state.value += 1
  802. cond.notify()
  803. p.join(5)
  804. self.assertTrue(success.value)
  805. @classmethod
  806. def _test_wait_result(cls, c, pid):
  807. with c:
  808. c.notify()
  809. time.sleep(1)
  810. if pid is not None:
  811. os.kill(pid, signal.SIGINT)
  812. def test_wait_result(self):
  813. if isinstance(self, ProcessesMixin) and sys.platform != 'win32':
  814. pid = os.getpid()
  815. else:
  816. pid = None
  817. c = self.Condition()
  818. with c:
  819. self.assertFalse(c.wait(0))
  820. self.assertFalse(c.wait(0.1))
  821. p = self.Process(target=self._test_wait_result, args=(c, pid))
  822. p.start()
  823. self.assertTrue(c.wait(10))
  824. if pid is not None:
  825. self.assertRaises(KeyboardInterrupt, c.wait, 10)
  826. p.join()
  827. class _TestEvent(BaseTestCase):
  828. @classmethod
  829. def _test_event(cls, event):
  830. time.sleep(TIMEOUT2)
  831. event.set()
  832. def test_event(self):
  833. event = self.Event()
  834. wait = TimingWrapper(event.wait)
  835. # Removed temporarily, due to API shear, this does not
  836. # work with threading._Event objects. is_set == isSet
  837. self.assertEqual(event.is_set(), False)
  838. # Removed, threading.Event.wait() will return the value of the __flag
  839. # instead of None. API Shear with the semaphore backed mp.Event
  840. self.assertEqual(wait(0.0), False)
  841. self.assertTimingAlmostEqual(wait.elapsed, 0.0)
  842. self.assertEqual(wait(TIMEOUT1), False)
  843. self.assertTimingAlmostEqual(wait.elapsed, TIMEOUT1)
  844. event.set()
  845. # See note above on the API differences
  846. self.assertEqual(event.is_set(), True)
  847. self.assertEqual(wait(), True)
  848. self.assertTimingAlmostEqual(wait.elapsed, 0.0)
  849. self.assertEqual(wait(TIMEOUT1), True)
  850. self.assertTimingAlmostEqual(wait.elapsed, 0.0)
  851. # self.assertEqual(event.is_set(), True)
  852. event.clear()
  853. #self.assertEqual(event.is_set(), False)
  854. p = self.Process(target=self._test_event, args=(event,))
  855. p.daemon = True
  856. p.start()
  857. self.assertEqual(wait(), True)
  858. #
  859. # Tests for Barrier - adapted from tests in test/lock_tests.py
  860. #
  861. # Many of the tests for threading.Barrier use a list as an atomic
  862. # counter: a value is appended to increment the counter, and the
  863. # length of the list gives the value. We use the class DummyList
  864. # for the same purpose.
  865. class _DummyList(object):
  866. def __init__(self):
  867. wrapper = multiprocessing.heap.BufferWrapper(struct.calcsize('i'))
  868. lock = multiprocessing.Lock()
  869. self.__setstate__((wrapper, lock))
  870. self._lengthbuf[0] = 0
  871. def __setstate__(self, state):
  872. (self._wrapper, self._lock) = state
  873. self._lengthbuf = self._wrapper.create_memoryview().cast('i')
  874. def __getstate__(self):
  875. return (self._wrapper, self._lock)
  876. def append(self, _):
  877. with self._lock:
  878. self._lengthbuf[0] += 1
  879. def __len__(self):
  880. with self._lock:
  881. return self._lengthbuf[0]
  882. def _wait():
  883. # A crude wait/yield function not relying on synchronization primitives.
  884. time.sleep(0.01)
  885. class Bunch(object):
  886. """
  887. A bunch of threads.
  888. """
  889. def __init__(self, namespace, f, args, n, wait_before_exit=False):
  890. """
  891. Construct a bunch of `n` threads running the same function `f`.
  892. If `wait_before_exit` is True, the threads won't terminate until
  893. do_finish() is called.
  894. """
  895. self.f = f
  896. self.args = args
  897. self.n = n
  898. self.started = namespace.DummyList()
  899. self.finished = namespace.DummyList()
  900. self._can_exit = namespace.Event()
  901. if not wait_before_exit:
  902. self._can_exit.set()
  903. for i in range(n):
  904. p = namespace.Process(target=self.task)
  905. p.daemon = True
  906. p.start()
  907. def task(self):
  908. pid = os.getpid()
  909. self.started.append(pid)
  910. try:
  911. self.f(*self.args)
  912. finally:
  913. self.finished.append(pid)
  914. self._can_exit.wait(30)
  915. assert self._can_exit.is_set()
  916. def wait_for_started(self):
  917. while len(self.started) < self.n:
  918. _wait()
  919. def wait_for_finished(self):
  920. while len(self.finished) < self.n:
  921. _wait()
  922. def do_finish(self):
  923. self._can_exit.set()
  924. class AppendTrue(object):
  925. def __init__(self, obj):
  926. self.obj = obj
  927. def __call__(self):
  928. self.obj.append(True)
  929. class _TestBarrier(BaseTestCase):
  930. """
  931. Tests for Barrier objects.
  932. """
  933. N = 5
  934. defaultTimeout = 30.0 # XXX Slow Windows buildbots need generous timeout
  935. def setUp(self):
  936. self.barrier = self.Barrier(self.N, timeout=self.defaultTimeout)
  937. def tearDown(self):
  938. self.barrier.abort()
  939. self.barrier = None
  940. def DummyList(self):
  941. if self.TYPE == 'threads':
  942. return []
  943. elif self.TYPE == 'manager':
  944. return self.manager.list()
  945. else:
  946. return _DummyList()
  947. def run_threads(self, f, args):
  948. b = Bunch(self, f, args, self.N-1)
  949. f(*args)
  950. b.wait_for_finished()
  951. @classmethod
  952. def multipass(cls, barrier, results, n):
  953. m = barrier.parties
  954. assert m == cls.N
  955. for i in range(n):
  956. results[0].append(True)
  957. assert len(results[1]) == i * m
  958. barrier.wait()
  959. results[1].append(True)
  960. assert len(results[0]) == (i + 1) * m
  961. barrier.wait()
  962. try:
  963. assert barrier.n_waiting == 0
  964. except NotImplementedError:
  965. pass
  966. assert not barrier.broken
  967. def test_barrier(self, passes=1):
  968. """
  969. Test that a barrier is passed in lockstep
  970. """
  971. results = [self.DummyList(), self.DummyList()]
  972. self.run_threads(self.multipass, (self.barrier, results, passes))
  973. def test_barrier_10(self):
  974. """
  975. Test that a barrier works for 10 consecutive runs
  976. """
  977. return self.test_barrier(10)
  978. @classmethod
  979. def _test_wait_return_f(cls, barrier, queue):
  980. res = barrier.wait()
  981. queue.put(res)
  982. def test_wait_return(self):
  983. """
  984. test the return value from barrier.wait
  985. """
  986. queue = self.Queue()
  987. self.run_threads(self._test_wait_return_f, (self.barrier, queue))
  988. results = [queue.get() for i in range(self.N)]
  989. self.assertEqual(results.count(0), 1)
  990. @classmethod
  991. def _test_action_f(cls, barrier, results):
  992. barrier.wait()
  993. if len(results) != 1:
  994. raise RuntimeError
  995. def test_action(self):
  996. """
  997. Test the 'action' callback
  998. """
  999. results = self.DummyList()
  1000. barrier = self.Barrier(self.N, action=AppendTrue(results))
  1001. self.run_threads(self._test_action_f, (barrier, results))
  1002. self.assertEqual(len(results), 1)
  1003. @classmethod
  1004. def _test_abort_f(cls, barrier, results1, results2):
  1005. try:
  1006. i = barrier.wait()
  1007. if i == cls.N//2:
  1008. raise RuntimeError
  1009. barrier.wait()
  1010. results1.append(True)
  1011. except threading.BrokenBarrierError:
  1012. results2.append(True)
  1013. except RuntimeError:
  1014. barrier.abort()
  1015. def test_abort(self):
  1016. """
  1017. Test that an abort will put the barrier in a broken state
  1018. """
  1019. results1 = self.DummyList()
  1020. results2 = self.DummyList()
  1021. self.run_threads(self._test_abort_f,
  1022. (self.barrier, results1, results2))
  1023. self.assertEqual(len(results1), 0)
  1024. self.assertEqual(len(results2), self.N-1)
  1025. self.assertTrue(self.barrier.broken)
  1026. @classmethod
  1027. def _test_reset_f(cls, barrier, results1, results2, results3):
  1028. i = barrier.wait()
  1029. if i == cls.N//2:
  1030. # Wait until the other threads are all in the barrier.
  1031. while barrier.n_waiting < cls.N-1:
  1032. time.sleep(0.001)
  1033. barrier.reset()
  1034. else:
  1035. try:
  1036. barrier.wait()
  1037. results1.append(True)
  1038. except threading.BrokenBarrierError:
  1039. results2.append(True)
  1040. # Now, pass the barrier again
  1041. barrier.wait()
  1042. results3.append(True)
  1043. def test_reset(self):
  1044. """
  1045. Test that a 'reset' on a barrier frees the waiting threads
  1046. """
  1047. results1 = self.DummyList()
  1048. results2 = self.DummyList()
  1049. results3 = self.DummyList()
  1050. self.run_threads(self._test_reset_f,
  1051. (self.barrier, results1, results2, results3))
  1052. self.assertEqual(len(results1), 0)
  1053. self.assertEqual(len(results2), self.N-1)
  1054. self.assertEqual(len(results3), self.N)
  1055. @classmethod
  1056. def _test_abort_and_reset_f(cls, barrier, barrier2,
  1057. results1, results2, results3):
  1058. try:
  1059. i = barrier.wait()
  1060. if i == cls.N//2:
  1061. raise RuntimeError
  1062. barrier.wait()
  1063. results1.append(True)
  1064. except threading.BrokenBarrierError:
  1065. results2.append(True)
  1066. except RuntimeError:
  1067. barrier.abort()
  1068. # Synchronize and reset the barrier. Must synchronize first so
  1069. # that everyone has left it when we reset, and after so that no
  1070. # one enters it before the reset.
  1071. if barrier2.wait() == cls.N//2:
  1072. barrier.reset()
  1073. barrier2.wait()
  1074. barrier.wait()
  1075. results3.append(True)
  1076. def test_abort_and_reset(self):
  1077. """
  1078. Test that a barrier can be reset after being broken.
  1079. """
  1080. results1 = self.DummyList()
  1081. results2 = self.DummyList()
  1082. results3 = self.DummyList()
  1083. barrier2 = self.Barrier(self.N)
  1084. self.run_threads(self._test_abort_and_reset_f,
  1085. (self.barrier, barrier2, results1, results2, results3))
  1086. self.assertEqual(len(results1), 0)
  1087. self.assertEqual(len(results2), self.N-1)
  1088. self.assertEqual(len(results3), self.N)
  1089. @classmethod
  1090. def _test_timeout_f(cls, barrier, results):
  1091. i = barrier.wait()
  1092. if i == cls.N//2:
  1093. # One thread is late!
  1094. time.sleep(1.0)
  1095. try:
  1096. barrier.wait(0.5)
  1097. except threading.BrokenBarrierError:
  1098. results.append(True)
  1099. def test_timeout(self):
  1100. """
  1101. Test wait(timeout)
  1102. """
  1103. results = self.DummyList()
  1104. self.run_threads(self._test_timeout_f, (self.barrier, results))
  1105. self.assertEqual(len(results), self.barrier.parties)
  1106. @classmethod
  1107. def _test_default_timeout_f(cls, barrier, results):
  1108. i = barrier.wait(cls.defaultTimeout)
  1109. if i == cls.N//2:
  1110. # One thread is later than the default timeout
  1111. time.sleep(1.0)
  1112. try:
  1113. barrier.wait()
  1114. except threading.BrokenBarrierError:
  1115. results.append(True)
  1116. def test_default_timeout(self):
  1117. """
  1118. Test the barrier's default timeout
  1119. """
  1120. barrier = self.Barrier(self.N, timeout=0.5)
  1121. results = self.DummyList()
  1122. self.run_threads(self._test_default_timeout_f, (barrier, results))
  1123. self.assertEqual(len(results), barrier.parties)
  1124. def test_single_thread(self):
  1125. b = self.Barrier(1)
  1126. b.wait()
  1127. b.wait()
  1128. @classmethod
  1129. def _test_thousand_f(cls, barrier, passes, conn, lock):
  1130. for i in range(passes):
  1131. barrier.wait()
  1132. with lock:
  1133. conn.send(i)
  1134. def test_thousand(self):
  1135. if self.TYPE == 'manager':
  1136. self.skipTest('test not appropriate for {}'.format(self.TYPE))
  1137. passes = 1000
  1138. lock = self.Lock()
  1139. conn, child_conn = self.Pipe(False)
  1140. for j in range(self.N):
  1141. p = self.Process(target=self._test_thousand_f,
  1142. args=(self.barrier, passes, child_conn, lock))
  1143. p.start()
  1144. for i in range(passes):
  1145. for j in range(self.N):
  1146. self.assertEqual(conn.recv(), i)
  1147. #
  1148. #
  1149. #
  1150. class _TestValue(BaseTestCase):
  1151. ALLOWED_TYPES = ('processes',)
  1152. codes_values = [
  1153. ('i', 4343, 24234),
  1154. ('d', 3.625, -4.25),
  1155. ('h', -232, 234),
  1156. ('c', latin('x'), latin('y'))
  1157. ]
  1158. def setUp(self):
  1159. if not HAS_SHAREDCTYPES:
  1160. self.skipTest("requires multiprocessing.sharedctypes")
  1161. @classmethod
  1162. def _test(cls, values):
  1163. for sv, cv in zip(values, cls.codes_values):
  1164. sv.value = cv[2]
  1165. def test_value(self, raw=False):
  1166. if raw:
  1167. values = [self.RawValue(code, value)
  1168. for code, value, _ in self.codes_values]
  1169. else:
  1170. values = [self.Value(code, value)
  1171. for code, value, _ in self.codes_values]
  1172. for sv, cv in zip(values, self.codes_values):
  1173. self.assertEqual(sv.value, cv[1])
  1174. proc = self.Process(target=self._test, args=(values,))
  1175. proc.daemon = True
  1176. proc.start()
  1177. proc.join()
  1178. for sv, cv in zip(values, self.codes_values):
  1179. self.assertEqual(sv.value, cv[2])
  1180. def test_rawvalue(self):
  1181. self.test_value(raw=True)
  1182. def test_getobj_getlock(self):
  1183. val1 = self.Value('i', 5)
  1184. lock1 = val1.get_lock()
  1185. obj1 = val1.get_obj()
  1186. val2 = self.Value('i', 5, lock=None)
  1187. lock2 = val2.get_lock()
  1188. obj2 = val2.get_obj()
  1189. lock = self.Lock()
  1190. val3 = self.Value('i', 5, lock=lock)
  1191. lock3 = val3.get_lock()
  1192. obj3 = val3.get_obj()
  1193. self.assertEqual(lock, lock3)
  1194. arr4 = self.Value('i', 5, lock=False)
  1195. self.assertFalse(hasattr(arr4, 'get_lock'))
  1196. self.assertFalse(hasattr(arr4, 'get_obj'))
  1197. self.assertRaises(AttributeError, self.Value, 'i', 5, lock='navalue')
  1198. arr5 = self.RawValue('i', 5)
  1199. self.assertFalse(hasattr(arr5, 'get_lock'))
  1200. self.assertFalse(hasattr(arr5, 'get_obj'))
  1201. class _TestArray(BaseTestCase):
  1202. ALLOWED_TYPES = ('processes',)
  1203. @classmethod
  1204. def f(cls, seq):
  1205. for i in range(1, len(seq)):
  1206. seq[i] += seq[i-1]
  1207. @unittest.skipIf(c_int is None, "requires _ctypes")
  1208. def test_array(self, raw=False):
  1209. seq = [680, 626, 934, 821, 150, 233, 548, 982, 714, 831]
  1210. if raw:
  1211. arr = self.RawArray('i', seq)
  1212. else:
  1213. arr = self.Array('i', seq)
  1214. self.assertEqual(len(arr), len(seq))
  1215. self.assertEqual(arr[3], seq[3])
  1216. self.assertEqual(list(arr[2:7]), list(seq[2:7]))
  1217. arr[4:8] = seq[4:8] = array.array('i', [1, 2, 3, 4])
  1218. self.assertEqual(list(arr[:]), seq)
  1219. self.f(seq)
  1220. p = self.Process(target=self.f, args=(arr,))
  1221. p.daemon = True
  1222. p.start()
  1223. p.join()
  1224. self.assertEqual(list(arr[:]), seq)
  1225. @unittest.skipIf(c_int is None, "requires _ctypes")
  1226. def test_array_from_size(self):
  1227. size = 10
  1228. # Test for zeroing (see issue #11675).
  1229. # The repetition below strengthens the test by increasing the chances
  1230. # of previously allocated non-zero memory being used for the new array
  1231. # on the 2nd and 3rd loops.
  1232. for _ in range(3):
  1233. arr = self.Array('i', size)
  1234. self.assertEqual(len(arr), size)
  1235. self.assertEqual(list(arr), [0] * size)
  1236. arr[:] = range(10)
  1237. self.assertEqual(list(arr), list(range(10)))
  1238. del arr
  1239. @unittest.skipIf(c_int is None, "requires _ctypes")
  1240. def test_rawarray(self):
  1241. self.test_array(raw=True)
  1242. @unittest.skipIf(c_int is None, "requires _ctypes")
  1243. def test_getobj_getlock_obj(self):
  1244. arr1 = self.Array('i', list(range(10)))
  1245. lock1 = arr1.get_lock()
  1246. obj1 = arr1.get_obj()
  1247. arr2 = self.Array('i', list(range(10)), lock=None)
  1248. lock2 = arr2.get_lock()
  1249. obj2 = arr2.get_obj()
  1250. lock = self.Lock()
  1251. arr3 = self.Array('i', list(range(10)), lock=lock)
  1252. lock3 = arr3.get_lock()
  1253. obj3 = arr3.get_obj()
  1254. self.assertEqual(lock, lock3)
  1255. arr4 = self.Array('i', range(10), lock=False)
  1256. self.assertFalse(hasattr(arr4, 'get_lock'))
  1257. self.assertFalse(hasattr(arr4, 'get_obj'))
  1258. self.assertRaises(AttributeError,
  1259. self.Array, 'i', range(10), lock='notalock')
  1260. arr5 = self.RawArray('i', range(10))
  1261. self.assertFalse(hasattr(arr5, 'get_lock'))
  1262. self.assertFalse(hasattr(arr5, 'get_obj'))
  1263. #
  1264. #
  1265. #
  1266. class _TestContainers(BaseTestCase):
  1267. ALLOWED_TYPES = ('manager',)
  1268. def test_list(self):
  1269. a = self.list(list(range(10)))
  1270. self.assertEqual(a[:], list(range(10)))
  1271. b = self.list()
  1272. self.assertEqual(b[:], [])
  1273. b.extend(list(range(5)))
  1274. self.assertEqual(b[:], list(range(5)))
  1275. self.assertEqual(b[2], 2)
  1276. self.assertEqual(b[2:10], [2,3,4])
  1277. b *= 2
  1278. self.assertEqual(b[:], [0, 1, 2, 3, 4, 0, 1, 2, 3, 4])
  1279. self.assertEqual(b + [5, 6], [0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6])
  1280. self.assertEqual(a[:], list(range(10)))
  1281. d = [a, b]
  1282. e = self.list(d)
  1283. self.assertEqual(
  1284. e[:],
  1285. [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]]
  1286. )
  1287. f = self.list([a])
  1288. a.append('hello')
  1289. self.assertEqual(f[:], [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'hello']])
  1290. def test_dict(self):
  1291. d = self.dict()
  1292. indices = list(range(65, 70))
  1293. for i in indices:
  1294. d[i] = chr(i)
  1295. self.assertEqual(d.copy(), dict((i, chr(i)) for i in indices))
  1296. self.assertEqual(sorted(d.keys()), indices)
  1297. self.assertEqual(sorted(d.values()), [chr(i) for i in indices])
  1298. self.assertEqual(sorted(d.items()), [(i, chr(i)) for i in indices])
  1299. def test_namespace(self):
  1300. n = self.Namespace()
  1301. n.name = 'Bob'
  1302. n.job = 'Builder'
  1303. n._hidden = 'hidden'
  1304. self.assertEqual((n.name, n.job), ('Bob', 'Builder'))
  1305. del n.job
  1306. self.assertEqual(str(n), "Namespace(name='Bob')")
  1307. self.assertTrue(hasattr(n, 'name'))
  1308. self.assertTrue(not hasattr(n, 'job'))
  1309. #
  1310. #
  1311. #
  1312. def sqr(x, wait=0.0):
  1313. time.sleep(wait)
  1314. return x*x
  1315. def mul(x, y):
  1316. return x*y
  1317. class _TestPool(BaseTestCase):
  1318. @classmethod
  1319. def setUpClass(cls):
  1320. super().setUpClass()
  1321. cls.pool = cls.Pool(4)
  1322. @classmethod
  1323. def tearDownClass(cls):
  1324. cls.pool.terminate()
  1325. cls.pool.join()
  1326. cls.pool = None
  1327. super().tearDownClass()
  1328. def test_apply(self):
  1329. papply = self.pool.apply
  1330. self.assertEqual(papply(sqr, (5,)), sqr(5))
  1331. self.assertEqual(papply(sqr, (), {'x':3}), sqr(x=3))
  1332. def test_map(self):
  1333. pmap = self.pool.map
  1334. self.assertEqual(pmap(sqr, list(range(10))), list(map(sqr, list(range(10)))))
  1335. self.assertEqual(pmap(sqr, list(range(100)), chunksize=20),
  1336. list(map(sqr, list(range(100)))))
  1337. def test_starmap(self):
  1338. psmap = self.pool.starmap
  1339. tuples = list(zip(range(10), range(9,-1, -1)))
  1340. self.assertEqual(psmap(mul, tuples),
  1341. list(itertools.starmap(mul, tuples)))
  1342. tuples = list(zip(range(100), range(99,-1, -1)))
  1343. self.assertEqual(psmap(mul, tuples, chunksize=20),
  1344. list(itertools.starmap(mul, tuples)))
  1345. def test_starmap_async(self):
  1346. tuples = list(zip(range(100), range(99,-1, -1)))
  1347. self.assertEqual(self.pool.starmap_async(mul, tuples).get(),
  1348. list(itertools.starmap(mul, tuples)))
  1349. def test_map_async(self):
  1350. self.assertEqual(self.pool.map_async(sqr, list(range(10))).get(),
  1351. list(map(sqr, list(range(10)))))
  1352. def test_map_async_callbacks(self):
  1353. call_args = self.manager.list() if self.TYPE == 'manager' else []
  1354. self.pool.map_async(int, ['1'],
  1355. callback=call_args.append,
  1356. error_callback=call_args.append).wait()
  1357. self.assertEqual(1, len(call_args))
  1358. self.assertEqual([1], call_args[0])
  1359. self.pool.map_async(int, ['a'],
  1360. callback=call_args.append,
  1361. error_callback=call_args.append).wait()
  1362. self.assertEqual(2, len(call_args))
  1363. self.assertIsInstance(call_args[1], ValueError)
  1364. def test_map_unplicklable(self):
  1365. # Issue #19425 -- failure to pickle should not cause a hang
  1366. if self.TYPE == 'threads':
  1367. self.skipTest('test not appropriate for {}'.format(self.TYPE))
  1368. class A(object):
  1369. def __reduce__(self):
  1370. raise RuntimeError('cannot pickle')
  1371. with self.assertRaises(RuntimeError):
  1372. self.pool.map(sqr, [A()]*10)
  1373. def test_map_chunksize(self):
  1374. try:
  1375. self.pool.map_async(sqr, [], chunksize=1).get(timeout=TIMEOUT1)
  1376. except multiprocessing.TimeoutError:
  1377. self.fail("pool.map_async with chunksize stalled on null list")
  1378. def test_async(self):
  1379. res = self.pool.apply_async(sqr, (7, TIMEOUT1,))
  1380. get = TimingWrapper(res.get)
  1381. self.assertEqual(get(), 49)
  1382. self.assertTimingAlmostEqual(get.elapsed, TIMEOUT1)
  1383. def test_async_timeout(self):
  1384. res = self.pool.apply_async(sqr, (6, TIMEOUT2 + 1.0))
  1385. get = TimingWrapper(res.get)
  1386. self.assertRaises(multiprocessing.TimeoutError, get, timeout=TIMEOUT2)
  1387. self.assertTimingAlmostEqual(get.elapsed, TIMEOUT2)
  1388. def test_imap(self):
  1389. it = self.pool.imap(sqr, list(range(10)))
  1390. self.assertEqual(list(it), list(map(sqr, list(range(10)))))
  1391. it = self.pool.imap(sqr, list(range(10)))
  1392. for i in range(10):
  1393. self.assertEqual(next(it), i*i)
  1394. self.assertRaises(StopIteration, it.__next__)
  1395. it = self.pool.imap(sqr, list(range(1000)), chunksize=100)
  1396. for i in range(1000):
  1397. self.assertEqual(next(it), i*i)
  1398. self.assertRaises(StopIteration, it.__next__)
  1399. def test_imap_unordered(self):
  1400. it = self.pool.imap_unordered(sqr, list(range(1000)))
  1401. self.assertEqual(sorted(it), list(map(sqr, list(range(1000)))))
  1402. it = self.pool.imap_unordered(sqr, list(range(1000)), chunksize=53)
  1403. self.assertEqual(sorted(it), list(map(sqr, list(range(1000)))))
  1404. def test_make_pool(self):
  1405. self.assertRaises(ValueError, multiprocessing.Pool, -1)
  1406. self.assertRaises(ValueError, multiprocessing.Pool, 0)
  1407. p = multiprocessing.Pool(3)
  1408. self.assertEqual(3, len(p._pool))
  1409. p.close()
  1410. p.join()
  1411. def test_terminate(self):
  1412. result = self.pool.map_async(
  1413. time.sleep, [0.1 for i in range(10000)], chunksize=1
  1414. )
  1415. self.pool.terminate()
  1416. join = TimingWrapper(self.pool.join)
  1417. join()
  1418. self.assertLess(join.elapsed, 0.5)
  1419. def test_empty_iterable(self):
  1420. # See Issue 12157
  1421. p = self.Pool(1)
  1422. self.assertEqual(p.map(sqr, []), [])
  1423. self.assertEqual(list(p.imap(sqr, [])), [])
  1424. self.assertEqual(list(p.imap_unordered(sqr, [])), [])
  1425. self.assertEqual(p.map_async(sqr, []).get(), [])
  1426. p.close()
  1427. p.join()
  1428. def test_context(self):
  1429. if self.TYPE == 'processes':
  1430. L = list(range(10))
  1431. expected = [sqr(i) for i in L]
  1432. with multiprocessing.Pool(2) as p:
  1433. r = p.map_async(sqr, L)
  1434. self.assertEqual(r.get(), expected)
  1435. self.assertRaises(ValueError, p.map_async, sqr, L)
  1436. @classmethod
  1437. def _test_traceback(cls):
  1438. raise RuntimeError(123) # some comment
  1439. def test_traceback(self):
  1440. # We want ensure that the traceback from the child process is
  1441. # contained in the traceback raised in the main process.
  1442. if self.TYPE == 'processes':
  1443. with self.Pool(1) as p:
  1444. try:
  1445. p.apply(self._test_traceback)
  1446. except Exception as e:
  1447. exc = e
  1448. else:
  1449. raise AssertionError('expected RuntimeError')
  1450. self.assertIs(type(exc), RuntimeError)
  1451. self.assertEqual(exc.args, (123,))
  1452. cause = exc.__cause__
  1453. self.assertIs(type(cause), multiprocessing.pool.RemoteTraceback)
  1454. self.assertIn('raise RuntimeError(123) # some comment', cause.tb)
  1455. with test.support.captured_stderr() as f1:
  1456. try:
  1457. raise exc
  1458. except RuntimeError:
  1459. sys.excepthook(*sys.exc_info())
  1460. self.assertIn('raise RuntimeError(123) # some comment',
  1461. f1.getvalue())
  1462. def raising():
  1463. raise KeyError("key")
  1464. def unpickleable_result():
  1465. return lambda: 42
  1466. class _TestPoolWorkerErrors(BaseTestCase):
  1467. ALLOWED_TYPES = ('processes', )
  1468. def test_async_error_callback(self):
  1469. p = multiprocessing.Pool(2)
  1470. scratchpad = [None]
  1471. def errback(exc):
  1472. scratchpad[0] = exc
  1473. res = p.apply_async(raising, error_callback=errback)
  1474. self.assertRaises(KeyError, res.get)
  1475. self.assertTrue(scratchpad[0])
  1476. self.assertIsInstance(scratchpad[0], KeyError)
  1477. p.close()
  1478. p.join()
  1479. def test_unpickleable_result(self):
  1480. from multiprocessing.pool import MaybeEncodingError
  1481. p = multiprocessing.Pool(2)
  1482. # Make sure we don't lose pool processes because of encoding errors.
  1483. for iteration in range(20):
  1484. scratchpad = [None]
  1485. def errback(exc):
  1486. scratchpad[0] = exc
  1487. res = p.apply_async(unpickleable_result, error_callback=errback)
  1488. self.assertRaises(MaybeEncodingError, res.get)
  1489. wrapped = scratchpad[0]
  1490. self.assertTrue(wrapped)
  1491. self.assertIsInstance(scratchpad[0], MaybeEncodingError)
  1492. self.assertIsNotNone(wrapped.exc)
  1493. self.assertIsNotNone(wrapped.value)
  1494. p.close()
  1495. p.join()
  1496. class _TestPoolWorkerLifetime(BaseTestCase):
  1497. ALLOWED_TYPES = ('processes', )
  1498. def test_pool_worker_lifetime(self):
  1499. p = multiprocessing.Pool(3, maxtasksperchild=10)
  1500. self.assertEqual(3, len(p._pool))
  1501. origworkerpids = [w.pid for w in p._pool]
  1502. # Run many tasks so each worker gets replaced (hopefully)
  1503. results = []
  1504. for i in range(100):
  1505. results.append(p.apply_async(sqr, (i, )))
  1506. # Fetch the results and verify we got the right answers,
  1507. # also ensuring all the tasks have completed.
  1508. for (j, res) in enumerate(results):
  1509. self.assertEqual(res.get(), sqr(j))
  1510. # Refill the pool
  1511. p._repopulate_pool()
  1512. # Wait until all workers are alive
  1513. # (countdown * DELTA = 5 seconds max startup process time)
  1514. countdown = 50
  1515. while countdown and not all(w.is_alive() for w in p._pool):
  1516. countdown -= 1
  1517. time.sleep(DELTA)
  1518. finalworkerpids = [w.pid for w in p._pool]
  1519. # All pids should be assigned. See issue #7805.
  1520. self.assertNotIn(None, origworkerpids)
  1521. self.assertNotIn(None, finalworkerpids)
  1522. # Finally, check that the worker pids have changed
  1523. self.assertNotEqual(sorted(origworkerpids), sorted(finalworkerpids))
  1524. p.close()
  1525. p.join()
  1526. def test_pool_worker_lifetime_early_close(self):
  1527. # Issue #10332: closing a pool whose workers have limited lifetimes
  1528. # before all the tasks completed would make join() hang.
  1529. p = multiprocessing.Pool(3, maxtasksperchild=1)
  1530. results = []
  1531. for i in range(6):
  1532. results.append(p.apply_async(sqr, (i, 0.3)))
  1533. p.close()
  1534. p.join()
  1535. # check the results
  1536. for (j, res) in enumerate(results):
  1537. self.assertEqual(res.get(), sqr(j))
  1538. #
  1539. # Test of creating a customized manager class
  1540. #
  1541. from multiprocessing.managers import BaseManager, BaseProxy, RemoteError
  1542. class FooBar(object):
  1543. def f(self):
  1544. return 'f()'
  1545. def g(self):
  1546. raise ValueError
  1547. def _h(self):
  1548. return '_h()'
  1549. def baz():
  1550. for i in range(10):
  1551. yield i*i
  1552. class IteratorProxy(BaseProxy):
  1553. _exposed_ = ('__next__',)
  1554. def __iter__(self):
  1555. return self
  1556. def __next__(self):
  1557. return self._callmethod('__next__')
  1558. class MyManager(BaseManager):
  1559. pass
  1560. MyManager.register('Foo', callable=FooBar)
  1561. MyManager.register('Bar', callable=FooBar, exposed=('f', '_h'))
  1562. MyManager.register('baz', callable=baz, proxytype=IteratorProxy)
  1563. class _TestMyManager(BaseTestCase):
  1564. ALLOWED_TYPES = ('manager',)
  1565. def test_mymanager(self):
  1566. manager = MyManager()
  1567. manager.start()
  1568. self.common(manager)
  1569. manager.shutdown()
  1570. # If the manager process exited cleanly then the exitcode
  1571. # will be zero. Otherwise (after a short timeout)
  1572. # terminate() is used, resulting in an exitcode of -SIGTERM.
  1573. self.assertEqual(manager._process.exitcode, 0)
  1574. def test_mymanager_context(self):
  1575. with MyManager() as manager:
  1576. self.common(manager)
  1577. self.assertEqual(manager._process.exitcode, 0)
  1578. def test_mymanager_context_prestarted(self):
  1579. manager = MyManager()
  1580. manager.start()
  1581. with manager:
  1582. self.common(manager)
  1583. self.assertEqual(manager._process.exitcode, 0)
  1584. def common(self, manager):
  1585. foo = manager.Foo()
  1586. bar = manager.Bar()
  1587. baz = manager.baz()
  1588. foo_methods = [name for name in ('f', 'g', '_h') if hasattr(foo, name)]
  1589. bar_methods = [name for name in ('f', 'g', '_h') if hasattr(bar, name)]
  1590. self.assertEqual(foo_methods, ['f', 'g'])
  1591. self.assertEqual(bar_methods, ['f', '_h'])
  1592. self.assertEqual(foo.f(), 'f()')
  1593. self.assertRaises(ValueError, foo.g)
  1594. self.assertEqual(foo._callmethod('f'), 'f()')
  1595. self.assertRaises(RemoteError, foo._callmethod, '_h')
  1596. self.assertEqual(bar.f(), 'f()')
  1597. self.assertEqual(bar._h(), '_h()')
  1598. self.assertEqual(bar._callmethod('f'), 'f()')
  1599. self.assertEqual(bar._callmethod('_h'), '_h()')
  1600. self.assertEqual(list(baz), [i*i for i in range(10)])
  1601. #
  1602. # Test of connecting to a remote server and using xmlrpclib for serialization
  1603. #
  1604. _queue = pyqueue.Queue()
  1605. def get_queue():
  1606. return _queue
  1607. class QueueManager(BaseManager):
  1608. '''manager class used by server process'''
  1609. QueueManager.register('get_queue', callable=get_queue)
  1610. class QueueManager2(BaseManager):
  1611. '''manager class which specifies the same interface as QueueManager'''
  1612. QueueManager2.register('get_queue')
  1613. SERIALIZER = 'xmlrpclib'
  1614. class _TestRemoteManager(BaseTestCase):
  1615. ALLOWED_TYPES = ('manager',)
  1616. @classmethod
  1617. def _putter(cls, address, authkey):
  1618. manager = QueueManager2(
  1619. address=address, authkey=authkey, serializer=SERIALIZER
  1620. )
  1621. manager.connect()
  1622. queue = manager.get_queue()
  1623. queue.put(('hello world', None, True, 2.25))
  1624. def test_remote(self):
  1625. authkey = os.urandom(32)
  1626. manager = QueueManager(
  1627. address=(test.support.HOST, 0), authkey=authkey, serializer=SERIALIZER
  1628. )
  1629. manager.start()
  1630. p = self.Process(target=self._putter, args=(manager.address, authkey))
  1631. p.daemon = True
  1632. p.start()
  1633. manager2 = QueueManager2(
  1634. address=manager.address, authkey=authkey, serializer=SERIALIZER
  1635. )
  1636. manager2.connect()
  1637. queue = manager2.get_queue()
  1638. # Note that xmlrpclib will deserialize object as a list not a tuple
  1639. self.assertEqual(queue.get(), ['hello world', None, True, 2.25])
  1640. # Because we are using xmlrpclib for serialization instead of
  1641. # pickle this will cause a serialization error.
  1642. self.assertRaises(Exception, queue.put, time.sleep)
  1643. # Make queue finalizer run before the server is stopped
  1644. del queue
  1645. manager.shutdown()
  1646. class _TestManagerRestart(BaseTestCase):
  1647. @classmethod
  1648. def _putter(cls, address, authkey):
  1649. manager = QueueManager(
  1650. address=address, authkey=authkey, serializer=SERIALIZER)
  1651. manager.connect()
  1652. queue = manager.get_queue()
  1653. queue.put('hello world')
  1654. def test_rapid_restart(self):
  1655. authkey = os.urandom(32)
  1656. manager = QueueManager(
  1657. address=(test.support.HOST, 0), authkey=authkey, serializer=SERIALIZER)
  1658. srvr = manager.get_server()
  1659. addr = srvr.address
  1660. # Close the connection.Listener socket which gets opened as a part
  1661. # of manager.get_server(). It's not needed for the test.
  1662. srvr.listener.close()
  1663. manager.start()
  1664. p = self.Process(target=self._putter, args=(manager.address, authkey))
  1665. p.daemon = True
  1666. p.start()
  1667. queue = manager.get_queue()
  1668. self.assertEqual(queue.get(), 'hello world')
  1669. del queue
  1670. manager.shutdown()
  1671. manager = QueueManager(
  1672. address=addr, authkey=authkey, serializer=SERIALIZER)
  1673. try:
  1674. manager.start()
  1675. except OSError as e:
  1676. if e.errno != errno.EADDRINUSE:
  1677. raise
  1678. # Retry after some time, in case the old socket was lingering
  1679. # (sporadic failure on buildbots)
  1680. time.sleep(1.0)
  1681. manager = QueueManager(
  1682. address=addr, authkey=authkey, serializer=SERIALIZER)
  1683. manager.shutdown()
  1684. #
  1685. #
  1686. #
  1687. SENTINEL = latin('')
  1688. class _TestConnection(BaseTestCase):
  1689. ALLOWED_TYPES = ('processes', 'threads')
  1690. @classmethod
  1691. def _echo(cls, conn):
  1692. for msg in iter(conn.recv_bytes, SENTINEL):
  1693. conn.send_bytes(msg)
  1694. conn.close()
  1695. def test_connection(self):
  1696. conn, child_conn = self.Pipe()
  1697. p = self.Process(target=self._echo, args=(child_conn,))
  1698. p.daemon = True
  1699. p.start()
  1700. seq = [1, 2.25, None]
  1701. msg = latin('hello world')
  1702. longmsg = msg * 10
  1703. arr = array.array('i', list(range(4)))
  1704. if self.TYPE == 'processes':
  1705. self.assertEqual(type(conn.fileno()), int)
  1706. self.assertEqual(conn.send(seq), None)
  1707. self.assertEqual(conn.recv(), seq)
  1708. self.assertEqual(conn.send_bytes(msg), None)
  1709. self.assertEqual(conn.recv_bytes(), msg)
  1710. if self.TYPE == 'processes':
  1711. buffer = array.array('i', [0]*10)
  1712. expected = list(arr) + [0] * (10 - len(arr))
  1713. self.assertEqual(conn.send_bytes(arr), None)
  1714. self.assertEqual(conn.recv_bytes_into(buffer),
  1715. len(arr) * buffer.itemsize)
  1716. self.assertEqual(list(buffer), expected)
  1717. buffer = array.array('i', [0]*10)
  1718. expected = [0] * 3 + list(arr) + [0] * (10 - 3 - len(arr))
  1719. self.assertEqual(conn.send_bytes(arr), None)
  1720. self.assertEqual(conn.recv_bytes_into(buffer, 3 * buffer.itemsize),
  1721. len(arr) * buffer.itemsize)
  1722. self.assertEqual(list(buffer), expected)
  1723. buffer = bytearray(latin(' ' * 40))
  1724. self.assertEqual(conn.send_bytes(longmsg), None)
  1725. try:
  1726. res = conn.recv_bytes_into(buffer)
  1727. except multiprocessing.BufferTooShort as e:
  1728. self.assertEqual(e.args, (longmsg,))
  1729. else:
  1730. self.fail('expected BufferTooShort, got %s' % res)
  1731. poll = TimingWrapper(conn.poll)
  1732. self.assertEqual(poll(), False)
  1733. self.assertTimingAlmostEqual(poll.elapsed, 0)
  1734. self.assertEqual(poll(-1), False)
  1735. self.assertTimingAlmostEqual(poll.elapsed, 0)
  1736. self.assertEqual(poll(TIMEOUT1), False)
  1737. self.assertTimingAlmostEqual(poll.elapsed, TIMEOUT1)
  1738. conn.send(None)
  1739. time.sleep(.1)
  1740. self.assertEqual(poll(TIMEOUT1), True)
  1741. self.assertTimingAlmostEqual(poll.elapsed, 0)
  1742. self.assertEqual(conn.recv(), None)
  1743. really_big_msg = latin('X') * (1024 * 1024 * 16) # 16Mb
  1744. conn.send_bytes(really_big_msg)
  1745. self.assertEqual(conn.recv_bytes(), really_big_msg)
  1746. conn.send_bytes(SENTINEL) # tell child to quit
  1747. child_conn.close()
  1748. if self.TYPE == 'processes':
  1749. self.assertEqual(conn.readable, True)
  1750. self.assertEqual(conn.writable, True)
  1751. self.assertRaises(EOFError, conn.recv)
  1752. self.assertRaises(EOFError, conn.recv_bytes)
  1753. p.join()
  1754. def test_duplex_false(self):
  1755. reader, writer = self.Pipe(duplex=False)
  1756. self.assertEqual(writer.send(1), None)
  1757. self.assertEqual(reader.recv(), 1)
  1758. if self.TYPE == 'processes':
  1759. self.assertEqual(reader.readable, True)
  1760. self.assertEqual(reader.writable, False)
  1761. self.assertEqual(writer.readable, False)
  1762. self.assertEqual(writer.writable, True)
  1763. self.assertRaises(OSError, reader.send, 2)
  1764. self.assertRaises(OSError, writer.recv)
  1765. self.assertRaises(OSError, writer.poll)
  1766. def test_spawn_close(self):
  1767. # We test that a pipe connection can be closed by parent
  1768. # process immediately after child is spawned. On Windows this
  1769. # would have sometimes failed on old versions because
  1770. # child_conn would be closed before the child got a chance to
  1771. # duplicate it.
  1772. conn, child_conn = self.Pipe()
  1773. p = self.Process(target=self._echo, args=(child_conn,))
  1774. p.daemon = True
  1775. p.start()
  1776. child_conn.close() # this might complete before child initializes
  1777. msg = latin('hello')
  1778. conn.send_bytes(msg)
  1779. self.assertEqual(conn.recv_bytes(), msg)
  1780. conn.send_bytes(SENTINEL)
  1781. conn.close()
  1782. p.join()
  1783. def test_sendbytes(self):
  1784. if self.TYPE != 'processes':
  1785. self.skipTest('test not appropriate for {}'.format(self.TYPE))
  1786. msg = latin('abcdefghijklmnopqrstuvwxyz')
  1787. a, b = self.Pipe()
  1788. a.send_bytes(msg)
  1789. self.assertEqual(b.recv_bytes(), msg)
  1790. a.send_bytes(msg, 5)
  1791. self.assertEqual(b.recv_bytes(), msg[5:])
  1792. a.send_bytes(msg, 7, 8)
  1793. self.assertEqual(b.recv_bytes(), msg[7:7+8])
  1794. a.send_bytes(msg, 26)
  1795. self.assertEqual(b.recv_bytes(), latin(''))
  1796. a.send_bytes(msg, 26, 0)
  1797. self.assertEqual(b.recv_bytes(), latin(''))
  1798. self.assertRaises(ValueError, a.send_bytes, msg, 27)
  1799. self.assertRaises(ValueError, a.send_bytes, msg, 22, 5)
  1800. self.assertRaises(ValueError, a.send_bytes, msg, 26, 1)
  1801. self.assertRaises(ValueError, a.send_bytes, msg, -1)
  1802. self.assertRaises(ValueError, a.send_bytes, msg, 4, -1)
  1803. @classmethod
  1804. def _is_fd_assigned(cls, fd):
  1805. try:
  1806. os.fstat(fd)
  1807. except OSError as e:
  1808. if e.errno == errno.EBADF:
  1809. return False
  1810. raise
  1811. else:
  1812. return True
  1813. @classmethod
  1814. def _writefd(cls, conn, data, create_dummy_fds=False):
  1815. if create_dummy_fds:
  1816. for i in range(0, 256):
  1817. if not cls._is_fd_assigned(i):
  1818. os.dup2(conn.fileno(), i)
  1819. fd = reduction.recv_handle(conn)
  1820. if msvcrt:
  1821. fd = msvcrt.open_osfhandle(fd, os.O_WRONLY)
  1822. os.write(fd, data)
  1823. os.close(fd)
  1824. @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction")
  1825. def test_fd_transfer(self):
  1826. if self.TYPE != 'processes':
  1827. self.skipTest("only makes sense with processes")
  1828. conn, child_conn = self.Pipe(duplex=True)
  1829. p = self.Process(target=self._writefd, args=(child_conn, b"foo"))
  1830. p.daemon = True
  1831. p.start()
  1832. self.addCleanup(test.support.unlink, test.support.TESTFN)
  1833. with open(test.support.TESTFN, "wb") as f:
  1834. fd = f.fileno()
  1835. if msvcrt:
  1836. fd = msvcrt.get_osfhandle(fd)
  1837. reduction.send_handle(conn, fd, p.pid)
  1838. p.join()
  1839. with open(test.support.TESTFN, "rb") as f:
  1840. self.assertEqual(f.read(), b"foo")
  1841. @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction")
  1842. @unittest.skipIf(sys.platform == "win32",
  1843. "test semantics don't make sense on Windows")
  1844. @unittest.skipIf(MAXFD <= 256,
  1845. "largest assignable fd number is too small")
  1846. @unittest.skipUnless(hasattr(os, "dup2"),
  1847. "test needs os.dup2()")
  1848. def test_large_fd_transfer(self):
  1849. # With fd > 256 (issue #11657)
  1850. if self.TYPE != 'processes':
  1851. self.skipTest("only makes sense with processes")
  1852. conn, child_conn = self.Pipe(duplex=True)
  1853. p = self.Process(target=self._writefd, args=(child_conn, b"bar", True))
  1854. p.daemon = True
  1855. p.start()
  1856. self.addCleanup(test.support.unlink, test.support.TESTFN)
  1857. with open(test.support.TESTFN, "wb") as f:
  1858. fd = f.fileno()
  1859. for newfd in range(256, MAXFD):
  1860. if not self._is_fd_assigned(newfd):
  1861. break
  1862. else:
  1863. self.fail("could not find an unassigned large file descriptor")
  1864. os.dup2(fd, newfd)
  1865. try:
  1866. reduction.send_handle(conn, newfd, p.pid)
  1867. finally:
  1868. os.close(newfd)
  1869. p.join()
  1870. with open(test.support.TESTFN, "rb") as f:
  1871. self.assertEqual(f.read(), b"bar")
  1872. @classmethod
  1873. def _send_data_without_fd(self, conn):
  1874. os.write(conn.fileno(), b"\0")
  1875. @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction")
  1876. @unittest.skipIf(sys.platform == "win32", "doesn't make sense on Windows")
  1877. def test_missing_fd_transfer(self):
  1878. # Check that exception is raised when received data is not
  1879. # accompanied by a file descriptor in ancillary data.
  1880. if self.TYPE != 'processes':
  1881. self.skipTest("only makes sense with processes")
  1882. conn, child_conn = self.Pipe(duplex=True)
  1883. p = self.Process(target=self._send_data_without_fd, args=(child_conn,))
  1884. p.daemon = True
  1885. p.start()
  1886. self.assertRaises(RuntimeError, reduction.recv_handle, conn)
  1887. p.join()
  1888. def test_context(self):
  1889. a, b = self.Pipe()
  1890. with a, b:
  1891. a.send(1729)
  1892. self.assertEqual(b.recv(), 1729)
  1893. if self.TYPE == 'processes':
  1894. self.assertFalse(a.closed)
  1895. self.assertFalse(b.closed)
  1896. if self.TYPE == 'processes':
  1897. self.assertTrue(a.closed)
  1898. self.assertTrue(b.closed)
  1899. self.assertRaises(OSError, a.recv)
  1900. self.assertRaises(OSError, b.recv)
  1901. class _TestListener(BaseTestCase):
  1902. ALLOWED_TYPES = ('processes',)
  1903. def test_multiple_bind(self):
  1904. for family in self.connection.families:
  1905. l = self.connection.Listener(family=family)
  1906. self.addCleanup(l.close)
  1907. self.assertRaises(OSError, self.connection.Listener,
  1908. l.address, family)
  1909. def test_context(self):
  1910. with self.connection.Listener() as l:
  1911. with self.connection.Client(l.address) as c:
  1912. with l.accept() as d:
  1913. c.send(1729)
  1914. self.assertEqual(d.recv(), 1729)
  1915. if self.TYPE == 'processes':
  1916. self.assertRaises(OSError, l.accept)
  1917. class _TestListenerClient(BaseTestCase):
  1918. ALLOWED_TYPES = ('processes', 'threads')
  1919. @classmethod
  1920. def _test(cls, address):
  1921. conn = cls.connection.Client(address)
  1922. conn.send('hello')
  1923. conn.close()
  1924. def test_listener_client(self):
  1925. for family in self.connection.families:
  1926. l = self.connection.Listener(family=family)
  1927. p = self.Process(target=self._test, args=(l.address,))
  1928. p.daemon = True
  1929. p.start()
  1930. conn = l.accept()
  1931. self.assertEqual(conn.recv(), 'hello')
  1932. p.join()
  1933. l.close()
  1934. def test_issue14725(self):
  1935. l = self.connection.Listener()
  1936. p = self.Process(target=self._test, args=(l.address,))
  1937. p.daemon = True
  1938. p.start()
  1939. time.sleep(1)
  1940. # On Windows the client process should by now have connected,
  1941. # written data and closed the pipe handle by now. This causes
  1942. # ConnectNamdedPipe() to fail with ERROR_NO_DATA. See Issue
  1943. # 14725.
  1944. conn = l.accept()
  1945. self.assertEqual(conn.recv(), 'hello')
  1946. conn.close()
  1947. p.join()
  1948. l.close()
  1949. def test_issue16955(self):
  1950. for fam in self.connection.families:
  1951. l = self.connection.Listener(family=fam)
  1952. c = self.connection.Client(l.address)
  1953. a = l.accept()
  1954. a.send_bytes(b"hello")
  1955. self.assertTrue(c.poll(1))
  1956. a.close()
  1957. c.close()
  1958. l.close()
  1959. class _TestPoll(BaseTestCase):
  1960. ALLOWED_TYPES = ('processes', 'threads')
  1961. def test_empty_string(self):
  1962. a, b = self.Pipe()
  1963. self.assertEqual(a.poll(), False)
  1964. b.send_bytes(b'')
  1965. self.assertEqual(a.poll(), True)
  1966. self.assertEqual(a.poll(), True)
  1967. @classmethod
  1968. def _child_strings(cls, conn, strings):
  1969. for s in strings:
  1970. time.sleep(0.1)
  1971. conn.send_bytes(s)
  1972. conn.close()
  1973. def test_strings(self):
  1974. strings = (b'hello', b'', b'a', b'b', b'', b'bye', b'', b'lop')
  1975. a, b = self.Pipe()
  1976. p = self.Process(target=self._child_strings, args=(b, strings))
  1977. p.start()
  1978. for s in strings:
  1979. for i in range(200):
  1980. if a.poll(0.01):
  1981. break
  1982. x = a.recv_bytes()
  1983. self.assertEqual(s, x)
  1984. p.join()
  1985. @classmethod
  1986. def _child_boundaries(cls, r):
  1987. # Polling may "pull" a message in to the child process, but we
  1988. # don't want it to pull only part of a message, as that would
  1989. # corrupt the pipe for any other processes which might later
  1990. # read from it.
  1991. r.poll(5)
  1992. def test_boundaries(self):
  1993. r, w = self.Pipe(False)
  1994. p = self.Process(target=self._child_boundaries, args=(r,))
  1995. p.start()
  1996. time.sleep(2)
  1997. L = [b"first", b"second"]
  1998. for obj in L:
  1999. w.send_bytes(obj)
  2000. w.close()
  2001. p.join()
  2002. self.assertIn(r.recv_bytes(), L)
  2003. @classmethod
  2004. def _child_dont_merge(cls, b):
  2005. b.send_bytes(b'a')
  2006. b.send_bytes(b'b')
  2007. b.send_bytes(b'cd')
  2008. def test_dont_merge(self):
  2009. a, b = self.Pipe()
  2010. self.assertEqual(a.poll(0.0), False)
  2011. self.assertEqual(a.poll(0.1), False)
  2012. p = self.Process(target=self._child_dont_merge, args=(b,))
  2013. p.start()
  2014. self.assertEqual(a.recv_bytes(), b'a')
  2015. self.assertEqual(a.poll(1.0), True)
  2016. self.assertEqual(a.poll(1.0), True)
  2017. self.assertEqual(a.recv_bytes(), b'b')
  2018. self.assertEqual(a.poll(1.0), True)
  2019. self.assertEqual(a.poll(1.0), True)
  2020. self.assertEqual(a.poll(0.0), True)
  2021. self.assertEqual(a.recv_bytes(), b'cd')
  2022. p.join()
  2023. #
  2024. # Test of sending connection and socket objects between processes
  2025. #
  2026. @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction")
  2027. class _TestPicklingConnections(BaseTestCase):
  2028. ALLOWED_TYPES = ('processes',)
  2029. @classmethod
  2030. def tearDownClass(cls):
  2031. from multiprocessing import resource_sharer
  2032. resource_sharer.stop(timeout=5)
  2033. @classmethod
  2034. def _listener(cls, conn, families):
  2035. for fam in families:
  2036. l = cls.connection.Listener(family=fam)
  2037. conn.send(l.address)
  2038. new_conn = l.accept()
  2039. conn.send(new_conn)
  2040. new_conn.close()
  2041. l.close()
  2042. l = socket.socket()
  2043. l.bind((test.support.HOST, 0))
  2044. l.listen(1)
  2045. conn.send(l.getsockname())
  2046. new_conn, addr = l.accept()
  2047. conn.send(new_conn)
  2048. new_conn.close()
  2049. l.close()
  2050. conn.recv()
  2051. @classmethod
  2052. def _remote(cls, conn):
  2053. for (address, msg) in iter(conn.recv, None):
  2054. client = cls.connection.Client(address)
  2055. client.send(msg.upper())
  2056. client.close()
  2057. address, msg = conn.recv()
  2058. client = socket.socket()
  2059. client.connect(address)
  2060. client.sendall(msg.upper())
  2061. client.close()
  2062. conn.close()
  2063. def test_pickling(self):
  2064. families = self.connection.families
  2065. lconn, lconn0 = self.Pipe()
  2066. lp = self.Process(target=self._listener, args=(lconn0, families))
  2067. lp.daemon = True
  2068. lp.start()
  2069. lconn0.close()
  2070. rconn, rconn0 = self.Pipe()
  2071. rp = self.Process(target=self._remote, args=(rconn0,))
  2072. rp.daemon = True
  2073. rp.start()
  2074. rconn0.close()
  2075. for fam in families:
  2076. msg = ('This connection uses family %s' % fam).encode('ascii')
  2077. address = lconn.recv()
  2078. rconn.send((address, msg))
  2079. new_conn = lconn.recv()
  2080. self.assertEqual(new_conn.recv(), msg.upper())
  2081. rconn.send(None)
  2082. msg = latin('This connection uses a normal socket')
  2083. address = lconn.recv()
  2084. rconn.send((address, msg))
  2085. new_conn = lconn.recv()
  2086. buf = []
  2087. while True:
  2088. s = new_conn.recv(100)
  2089. if not s:
  2090. break
  2091. buf.append(s)
  2092. buf = b''.join(buf)
  2093. self.assertEqual(buf, msg.upper())
  2094. new_conn.close()
  2095. lconn.send(None)
  2096. rconn.close()
  2097. lconn.close()
  2098. lp.join()
  2099. rp.join()
  2100. @classmethod
  2101. def child_access(cls, conn):
  2102. w = conn.recv()
  2103. w.send('all is well')
  2104. w.close()
  2105. r = conn.recv()
  2106. msg = r.recv()
  2107. conn.send(msg*2)
  2108. conn.close()
  2109. def test_access(self):
  2110. # On Windows, if we do not specify a destination pid when
  2111. # using DupHandle then we need to be careful to use the
  2112. # correct access flags for DuplicateHandle(), or else
  2113. # DupHandle.detach() will raise PermissionError. For example,
  2114. # for a read only pipe handle we should use
  2115. # access=FILE_GENERIC_READ. (Unfortunately
  2116. # DUPLICATE_SAME_ACCESS does not work.)
  2117. conn, child_conn = self.Pipe()
  2118. p = self.Process(target=self.child_access, args=(child_conn,))
  2119. p.daemon = True
  2120. p.start()
  2121. child_conn.close()
  2122. r, w = self.Pipe(duplex=False)
  2123. conn.send(w)
  2124. w.close()
  2125. self.assertEqual(r.recv(), 'all is well')
  2126. r.close()
  2127. r, w = self.Pipe(duplex=False)
  2128. conn.send(r)
  2129. r.close()
  2130. w.send('foobar')
  2131. w.close()
  2132. self.assertEqual(conn.recv(), 'foobar'*2)
  2133. #
  2134. #
  2135. #
  2136. class _TestHeap(BaseTestCase):
  2137. ALLOWED_TYPES = ('processes',)
  2138. def test_heap(self):
  2139. iterations = 5000
  2140. maxblocks = 50
  2141. blocks = []
  2142. # create and destroy lots of blocks of different sizes
  2143. for i in range(iterations):
  2144. size = int(random.lognormvariate(0, 1) * 1000)
  2145. b = multiprocessing.heap.BufferWrapper(size)
  2146. blocks.append(b)
  2147. if len(blocks) > maxblocks:
  2148. i = random.randrange(maxblocks)
  2149. del blocks[i]
  2150. # get the heap object
  2151. heap = multiprocessing.heap.BufferWrapper._heap
  2152. # verify the state of the heap
  2153. all = []
  2154. occupied = 0
  2155. heap._lock.acquire()
  2156. self.addCleanup(heap._lock.release)
  2157. for L in list(heap._len_to_seq.values()):
  2158. for arena, start, stop in L:
  2159. all.append((heap._arenas.index(arena), start, stop,
  2160. stop-start, 'free'))
  2161. for arena, start, stop in heap._allocated_blocks:
  2162. all.append((heap._arenas.index(arena), start, stop,
  2163. stop-start, 'occupied'))
  2164. occupied += (stop-start)
  2165. all.sort()
  2166. for i in range(len(all)-1):
  2167. (arena, start, stop) = all[i][:3]
  2168. (narena, nstart, nstop) = all[i+1][:3]
  2169. self.assertTrue((arena != narena and nstart == 0) or
  2170. (stop == nstart))
  2171. def test_free_from_gc(self):
  2172. # Check that freeing of blocks by the garbage collector doesn't deadlock
  2173. # (issue #12352).
  2174. # Make sure the GC is enabled, and set lower collection thresholds to
  2175. # make collections more frequent (and increase the probability of
  2176. # deadlock).
  2177. if not gc.isenabled():
  2178. gc.enable()
  2179. self.addCleanup(gc.disable)
  2180. thresholds = gc.get_threshold()
  2181. self.addCleanup(gc.set_threshold, *thresholds)
  2182. gc.set_threshold(10)
  2183. # perform numerous block allocations, with cyclic references to make
  2184. # sure objects are collected asynchronously by the gc
  2185. for i in range(5000):
  2186. a = multiprocessing.heap.BufferWrapper(1)
  2187. b = multiprocessing.heap.BufferWrapper(1)
  2188. # circular references
  2189. a.buddy = b
  2190. b.buddy = a
  2191. #
  2192. #
  2193. #
  2194. class _Foo(Structure):
  2195. _fields_ = [
  2196. ('x', c_int),
  2197. ('y', c_double)
  2198. ]
  2199. class _TestSharedCTypes(BaseTestCase):
  2200. ALLOWED_TYPES = ('processes',)
  2201. def setUp(self):
  2202. if not HAS_SHAREDCTYPES:
  2203. self.skipTest("requires multiprocessing.sharedctypes")
  2204. @classmethod
  2205. def _double(cls, x, y, foo, arr, string):
  2206. x.value *= 2
  2207. y.value *= 2
  2208. foo.x *= 2
  2209. foo.y *= 2
  2210. string.value *= 2
  2211. for i in range(len(arr)):
  2212. arr[i] *= 2
  2213. def test_sharedctypes(self, lock=False):
  2214. x = Value('i', 7, lock=lock)
  2215. y = Value(c_double, 1.0/3.0, lock=lock)
  2216. foo = Value(_Foo, 3, 2, lock=lock)
  2217. arr = self.Array('d', list(range(10)), lock=lock)
  2218. string = self.Array('c', 20, lock=lock)
  2219. string.value = latin('hello')
  2220. p = self.Process(target=self._double, args=(x, y, foo, arr, string))
  2221. p.daemon = True
  2222. p.start()
  2223. p.join()
  2224. self.assertEqual(x.value, 14)
  2225. self.assertAlmostEqual(y.value, 2.0/3.0)
  2226. self.assertEqual(foo.x, 6)
  2227. self.assertAlmostEqual(foo.y, 4.0)
  2228. for i in range(10):
  2229. self.assertAlmostEqual(arr[i], i*2)
  2230. self.assertEqual(string.value, latin('hellohello'))
  2231. def test_synchronize(self):
  2232. self.test_sharedctypes(lock=True)
  2233. def test_copy(self):
  2234. foo = _Foo(2, 5.0)
  2235. bar = copy(foo)
  2236. foo.x = 0
  2237. foo.y = 0
  2238. self.assertEqual(bar.x, 2)
  2239. self.assertAlmostEqual(bar.y, 5.0)
  2240. #
  2241. #
  2242. #
  2243. class _TestFinalize(BaseTestCase):
  2244. ALLOWED_TYPES = ('processes',)
  2245. @classmethod
  2246. def _test_finalize(cls, conn):
  2247. class Foo(object):
  2248. pass
  2249. a = Foo()
  2250. util.Finalize(a, conn.send, args=('a',))
  2251. del a # triggers callback for a
  2252. b = Foo()
  2253. close_b = util.Finalize(b, conn.send, args=('b',))
  2254. close_b() # triggers callback for b
  2255. close_b() # does nothing because callback has already been called
  2256. del b # does nothing because callback has already been called
  2257. c = Foo()
  2258. util.Finalize(c, conn.send, args=('c',))
  2259. d10 = Foo()
  2260. util.Finalize(d10, conn.send, args=('d10',), exitpriority=1)
  2261. d01 = Foo()
  2262. util.Finalize(d01, conn.send, args=('d01',), exitpriority=0)
  2263. d02 = Foo()
  2264. util.Finalize(d02, conn.send, args=('d02',), exitpriority=0)
  2265. d03 = Foo()
  2266. util.Finalize(d03, conn.send, args=('d03',), exitpriority=0)
  2267. util.Finalize(None, conn.send, args=('e',), exitpriority=-10)
  2268. util.Finalize(None, conn.send, args=('STOP',), exitpriority=-100)
  2269. # call multiprocessing's cleanup function then exit process without
  2270. # garbage collecting locals
  2271. util._exit_function()
  2272. conn.close()
  2273. os._exit(0)
  2274. def test_finalize(self):
  2275. conn, child_conn = self.Pipe()
  2276. p = self.Process(target=self._test_finalize, args=(child_conn,))
  2277. p.daemon = True
  2278. p.start()
  2279. p.join()
  2280. result = [obj for obj in iter(conn.recv, 'STOP')]
  2281. self.assertEqual(result, ['a', 'b', 'd10', 'd03', 'd02', 'd01', 'e'])
  2282. #
  2283. # Test that from ... import * works for each module
  2284. #
  2285. class _TestImportStar(unittest.TestCase):
  2286. def get_module_names(self):
  2287. import glob
  2288. folder = os.path.dirname(multiprocessing.__file__)
  2289. pattern = os.path.join(folder, '*.py')
  2290. files = glob.glob(pattern)
  2291. modules = [os.path.splitext(os.path.split(f)[1])[0] for f in files]
  2292. modules = ['multiprocessing.' + m for m in modules]
  2293. modules.remove('multiprocessing.__init__')
  2294. modules.append('multiprocessing')
  2295. return modules
  2296. def test_import(self):
  2297. modules = self.get_module_names()
  2298. if sys.platform == 'win32':
  2299. modules.remove('multiprocessing.popen_fork')
  2300. modules.remove('multiprocessing.popen_forkserver')
  2301. modules.remove('multiprocessing.popen_spawn_posix')
  2302. else:
  2303. modules.remove('multiprocessing.popen_spawn_win32')
  2304. if not HAS_REDUCTION:
  2305. modules.remove('multiprocessing.popen_forkserver')
  2306. if c_int is None:
  2307. # This module requires _ctypes
  2308. modules.remove('multiprocessing.sharedctypes')
  2309. for name in modules:
  2310. __import__(name)
  2311. mod = sys.modules[name]
  2312. self.assertTrue(hasattr(mod, '__all__'), name)
  2313. for attr in mod.__all__:
  2314. self.assertTrue(
  2315. hasattr(mod, attr),
  2316. '%r does not have attribute %r' % (mod, attr)
  2317. )
  2318. #
  2319. # Quick test that logging works -- does not test logging output
  2320. #
  2321. class _TestLogging(BaseTestCase):
  2322. ALLOWED_TYPES = ('processes',)
  2323. def test_enable_logging(self):
  2324. logger = multiprocessing.get_logger()
  2325. logger.setLevel(util.SUBWARNING)
  2326. self.assertTrue(logger is not None)
  2327. logger.debug('this will not be printed')
  2328. logger.info('nor will this')
  2329. logger.setLevel(LOG_LEVEL)
  2330. @classmethod
  2331. def _test_level(cls, conn):
  2332. logger = multiprocessing.get_logger()
  2333. conn.send(logger.getEffectiveLevel())
  2334. def test_level(self):
  2335. LEVEL1 = 32
  2336. LEVEL2 = 37
  2337. logger = multiprocessing.get_logger()
  2338. root_logger = logging.getLogger()
  2339. root_level = root_logger.level
  2340. reader, writer = multiprocessing.Pipe(duplex=False)
  2341. logger.setLevel(LEVEL1)
  2342. p = self.Process(target=self._test_level, args=(writer,))
  2343. p.daemon = True
  2344. p.start()
  2345. self.assertEqual(LEVEL1, reader.recv())
  2346. logger.setLevel(logging.NOTSET)
  2347. root_logger.setLevel(LEVEL2)
  2348. p = self.Process(target=self._test_level, args=(writer,))
  2349. p.daemon = True
  2350. p.start()
  2351. self.assertEqual(LEVEL2, reader.recv())
  2352. root_logger.setLevel(root_level)
  2353. logger.setLevel(level=LOG_LEVEL)
  2354. # class _TestLoggingProcessName(BaseTestCase):
  2355. #
  2356. # def handle(self, record):
  2357. # assert record.processName == multiprocessing.current_process().name
  2358. # self.__handled = True
  2359. #
  2360. # def test_logging(self):
  2361. # handler = logging.Handler()
  2362. # handler.handle = self.handle
  2363. # self.__handled = False
  2364. # # Bypass getLogger() and side-effects
  2365. # logger = logging.getLoggerClass()(
  2366. # 'multiprocessing.test.TestLoggingProcessName')
  2367. # logger.addHandler(handler)
  2368. # logger.propagate = False
  2369. #
  2370. # logger.warn('foo')
  2371. # assert self.__handled
  2372. #
  2373. # Check that Process.join() retries if os.waitpid() fails with EINTR
  2374. #
  2375. class _TestPollEintr(BaseTestCase):
  2376. ALLOWED_TYPES = ('processes',)
  2377. @classmethod
  2378. def _killer(cls, pid):
  2379. time.sleep(0.1)
  2380. os.kill(pid, signal.SIGUSR1)
  2381. @unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1')
  2382. def test_poll_eintr(self):
  2383. got_signal = [False]
  2384. def record(*args):
  2385. got_signal[0] = True
  2386. pid = os.getpid()
  2387. oldhandler = signal.signal(signal.SIGUSR1, record)
  2388. try:
  2389. killer = self.Process(target=self._killer, args=(pid,))
  2390. killer.start()
  2391. try:
  2392. p = self.Process(target=time.sleep, args=(2,))
  2393. p.start()
  2394. p.join()
  2395. finally:
  2396. killer.join()
  2397. self.assertTrue(got_signal[0])
  2398. self.assertEqual(p.exitcode, 0)
  2399. finally:
  2400. signal.signal(signal.SIGUSR1, oldhandler)
  2401. #
  2402. # Test to verify handle verification, see issue 3321
  2403. #
  2404. class TestInvalidHandle(unittest.TestCase):
  2405. @unittest.skipIf(WIN32, "skipped on Windows")
  2406. def test_invalid_handles(self):
  2407. conn = multiprocessing.connection.Connection(44977608)
  2408. # check that poll() doesn't crash
  2409. try:
  2410. conn.poll()
  2411. except (ValueError, OSError):
  2412. pass
  2413. finally:
  2414. # Hack private attribute _handle to avoid printing an error
  2415. # in conn.__del__
  2416. conn._handle = None
  2417. self.assertRaises((ValueError, OSError),
  2418. multiprocessing.connection.Connection, -1)
  2419. class OtherTest(unittest.TestCase):
  2420. # TODO: add more tests for deliver/answer challenge.
  2421. def test_deliver_challenge_auth_failure(self):
  2422. class _FakeConnection(object):
  2423. def recv_bytes(self, size):
  2424. return b'something bogus'
  2425. def send_bytes(self, data):
  2426. pass
  2427. self.assertRaises(multiprocessing.AuthenticationError,
  2428. multiprocessing.connection.deliver_challenge,
  2429. _FakeConnection(), b'abc')
  2430. def test_answer_challenge_auth_failure(self):
  2431. class _FakeConnection(object):
  2432. def __init__(self):
  2433. self.count = 0
  2434. def recv_bytes(self, size):
  2435. self.count += 1
  2436. if self.count == 1:
  2437. return multiprocessing.connection.CHALLENGE
  2438. elif self.count == 2:
  2439. return b'something bogus'
  2440. return b''
  2441. def send_bytes(self, data):
  2442. pass
  2443. self.assertRaises(multiprocessing.AuthenticationError,
  2444. multiprocessing.connection.answer_challenge,
  2445. _FakeConnection(), b'abc')
  2446. #
  2447. # Test Manager.start()/Pool.__init__() initializer feature - see issue 5585
  2448. #
  2449. def initializer(ns):
  2450. ns.test += 1
  2451. class TestInitializers(unittest.TestCase):
  2452. def setUp(self):
  2453. self.mgr = multiprocessing.Manager()
  2454. self.ns = self.mgr.Namespace()
  2455. self.ns.test = 0
  2456. def tearDown(self):
  2457. self.mgr.shutdown()
  2458. self.mgr.join()
  2459. def test_manager_initializer(self):
  2460. m = multiprocessing.managers.SyncManager()
  2461. self.assertRaises(TypeError, m.start, 1)
  2462. m.start(initializer, (self.ns,))
  2463. self.assertEqual(self.ns.test, 1)
  2464. m.shutdown()
  2465. m.join()
  2466. def test_pool_initializer(self):
  2467. self.assertRaises(TypeError, multiprocessing.Pool, initializer=1)
  2468. p = multiprocessing.Pool(1, initializer, (self.ns,))
  2469. p.close()
  2470. p.join()
  2471. self.assertEqual(self.ns.test, 1)
  2472. #
  2473. # Issue 5155, 5313, 5331: Test process in processes
  2474. # Verifies os.close(sys.stdin.fileno) vs. sys.stdin.close() behavior
  2475. #
  2476. def _this_sub_process(q):
  2477. try:
  2478. item = q.get(block=False)
  2479. except pyqueue.Empty:
  2480. pass
  2481. def _test_process(q):
  2482. queue = multiprocessing.Queue()
  2483. subProc = multiprocessing.Process(target=_this_sub_process, args=(queue,))
  2484. subProc.daemon = True
  2485. subProc.start()
  2486. subProc.join()
  2487. def _afunc(x):
  2488. return x*x
  2489. def pool_in_process():
  2490. pool = multiprocessing.Pool(processes=4)
  2491. x = pool.map(_afunc, [1, 2, 3, 4, 5, 6, 7])
  2492. pool.close()
  2493. pool.join()
  2494. class _file_like(object):
  2495. def __init__(self, delegate):
  2496. self._delegate = delegate
  2497. self._pid = None
  2498. @property
  2499. def cache(self):
  2500. pid = os.getpid()
  2501. # There are no race conditions since fork keeps only the running thread
  2502. if pid != self._pid:
  2503. self._pid = pid
  2504. self._cache = []
  2505. return self._cache
  2506. def write(self, data):
  2507. self.cache.append(data)
  2508. def flush(self):
  2509. self._delegate.write(''.join(self.cache))
  2510. self._cache = []
  2511. class TestStdinBadfiledescriptor(unittest.TestCase):
  2512. def test_queue_in_process(self):
  2513. queue = multiprocessing.Queue()
  2514. proc = multiprocessing.Process(target=_test_process, args=(queue,))
  2515. proc.start()
  2516. proc.join()
  2517. def test_pool_in_process(self):
  2518. p = multiprocessing.Process(target=pool_in_process)
  2519. p.start()
  2520. p.join()
  2521. def test_flushing(self):
  2522. sio = io.StringIO()
  2523. flike = _file_like(sio)
  2524. flike.write('foo')
  2525. proc = multiprocessing.Process(target=lambda: flike.flush())
  2526. flike.flush()
  2527. assert sio.getvalue() == 'foo'
  2528. class TestWait(unittest.TestCase):
  2529. @classmethod
  2530. def _child_test_wait(cls, w, slow):
  2531. for i in range(10):
  2532. if slow:
  2533. time.sleep(random.random()*0.1)
  2534. w.send((i, os.getpid()))
  2535. w.close()
  2536. def test_wait(self, slow=False):
  2537. from multiprocessing.connection import wait
  2538. readers = []
  2539. procs = []
  2540. messages = []
  2541. for i in range(4):
  2542. r, w = multiprocessing.Pipe(duplex=False)
  2543. p = multiprocessing.Process(target=self._child_test_wait, args=(w, slow))
  2544. p.daemon = True
  2545. p.start()
  2546. w.close()
  2547. readers.append(r)
  2548. procs.append(p)
  2549. self.addCleanup(p.join)
  2550. while readers:
  2551. for r in wait(readers):
  2552. try:
  2553. msg = r.recv()
  2554. except EOFError:
  2555. readers.remove(r)
  2556. r.close()
  2557. else:
  2558. messages.append(msg)
  2559. messages.sort()
  2560. expected = sorted((i, p.pid) for i in range(10) for p in procs)
  2561. self.assertEqual(messages, expected)
  2562. @classmethod
  2563. def _child_test_wait_socket(cls, address, slow):
  2564. s = socket.socket()
  2565. s.connect(address)
  2566. for i in range(10):
  2567. if slow:
  2568. time.sleep(random.random()*0.1)
  2569. s.sendall(('%s\n' % i).encode('ascii'))
  2570. s.close()
  2571. def test_wait_socket(self, slow=False):
  2572. from multiprocessing.connection import wait
  2573. l = socket.socket()
  2574. l.bind((test.support.HOST, 0))
  2575. l.listen(4)
  2576. addr = l.getsockname()
  2577. readers = []
  2578. procs = []
  2579. dic = {}
  2580. for i in range(4):
  2581. p = multiprocessing.Process(target=self._child_test_wait_socket,
  2582. args=(addr, slow))
  2583. p.daemon = True
  2584. p.start()
  2585. procs.append(p)
  2586. self.addCleanup(p.join)
  2587. for i in range(4):
  2588. r, _ = l.accept()
  2589. readers.append(r)
  2590. dic[r] = []
  2591. l.close()
  2592. while readers:
  2593. for r in wait(readers):
  2594. msg = r.recv(32)
  2595. if not msg:
  2596. readers.remove(r)
  2597. r.close()
  2598. else:
  2599. dic[r].append(msg)
  2600. expected = ''.join('%s\n' % i for i in range(10)).encode('ascii')
  2601. for v in dic.values():
  2602. self.assertEqual(b''.join(v), expected)
  2603. def test_wait_slow(self):
  2604. self.test_wait(True)
  2605. def test_wait_socket_slow(self):
  2606. self.test_wait_socket(True)
  2607. def test_wait_timeout(self):
  2608. from multiprocessing.connection import wait
  2609. expected = 5
  2610. a, b = multiprocessing.Pipe()
  2611. start = time.time()
  2612. res = wait([a, b], expected)
  2613. delta = time.time() - start
  2614. self.assertEqual(res, [])
  2615. self.assertLess(delta, expected * 2)
  2616. self.assertGreater(delta, expected * 0.5)
  2617. b.send(None)
  2618. start = time.time()
  2619. res = wait([a, b], 20)
  2620. delta = time.time() - start
  2621. self.assertEqual(res, [a])
  2622. self.assertLess(delta, 0.4)
  2623. @classmethod
  2624. def signal_and_sleep(cls, sem, period):
  2625. sem.release()
  2626. time.sleep(period)
  2627. def test_wait_integer(self):
  2628. from multiprocessing.connection import wait
  2629. expected = 3
  2630. sorted_ = lambda l: sorted(l, key=lambda x: id(x))
  2631. sem = multiprocessing.Semaphore(0)
  2632. a, b = multiprocessing.Pipe()
  2633. p = multiprocessing.Process(target=self.signal_and_sleep,
  2634. args=(sem, expected))
  2635. p.start()
  2636. self.assertIsInstance(p.sentinel, int)
  2637. self.assertTrue(sem.acquire(timeout=20))
  2638. start = time.time()
  2639. res = wait([a, p.sentinel, b], expected + 20)
  2640. delta = time.time() - start
  2641. self.assertEqual(res, [p.sentinel])
  2642. self.assertLess(delta, expected + 2)
  2643. self.assertGreater(delta, expected - 2)
  2644. a.send(None)
  2645. start = time.time()
  2646. res = wait([a, p.sentinel, b], 20)
  2647. delta = time.time() - start
  2648. self.assertEqual(sorted_(res), sorted_([p.sentinel, b]))
  2649. self.assertLess(delta, 0.4)
  2650. b.send(None)
  2651. start = time.time()
  2652. res = wait([a, p.sentinel, b], 20)
  2653. delta = time.time() - start
  2654. self.assertEqual(sorted_(res), sorted_([a, p.sentinel, b]))
  2655. self.assertLess(delta, 0.4)
  2656. p.terminate()
  2657. p.join()
  2658. def test_neg_timeout(self):
  2659. from multiprocessing.connection import wait
  2660. a, b = multiprocessing.Pipe()
  2661. t = time.time()
  2662. res = wait([a], timeout=-1)
  2663. t = time.time() - t
  2664. self.assertEqual(res, [])
  2665. self.assertLess(t, 1)
  2666. a.close()
  2667. b.close()
  2668. #
  2669. # Issue 14151: Test invalid family on invalid environment
  2670. #
  2671. class TestInvalidFamily(unittest.TestCase):
  2672. @unittest.skipIf(WIN32, "skipped on Windows")
  2673. def test_invalid_family(self):
  2674. with self.assertRaises(ValueError):
  2675. multiprocessing.connection.Listener(r'\\.\test')
  2676. @unittest.skipUnless(WIN32, "skipped on non-Windows platforms")
  2677. def test_invalid_family_win32(self):
  2678. with self.assertRaises(ValueError):
  2679. multiprocessing.connection.Listener('/var/test.pipe')
  2680. #
  2681. # Issue 12098: check sys.flags of child matches that for parent
  2682. #
  2683. class TestFlags(unittest.TestCase):
  2684. @classmethod
  2685. def run_in_grandchild(cls, conn):
  2686. conn.send(tuple(sys.flags))
  2687. @classmethod
  2688. def run_in_child(cls):
  2689. import json
  2690. r, w = multiprocessing.Pipe(duplex=False)
  2691. p = multiprocessing.Process(target=cls.run_in_grandchild, args=(w,))
  2692. p.start()
  2693. grandchild_flags = r.recv()
  2694. p.join()
  2695. r.close()
  2696. w.close()
  2697. flags = (tuple(sys.flags), grandchild_flags)
  2698. print(json.dumps(flags))
  2699. def test_flags(self):
  2700. import json, subprocess
  2701. # start child process using unusual flags
  2702. prog = ('from test._test_multiprocessing import TestFlags; ' +
  2703. 'TestFlags.run_in_child()')
  2704. data = subprocess.check_output(
  2705. [sys.executable, '-E', '-S', '-O', '-c', prog])
  2706. child_flags, grandchild_flags = json.loads(data.decode('ascii'))
  2707. self.assertEqual(child_flags, grandchild_flags)
  2708. #
  2709. # Test interaction with socket timeouts - see Issue #6056
  2710. #
  2711. class TestTimeouts(unittest.TestCase):
  2712. @classmethod
  2713. def _test_timeout(cls, child, address):
  2714. time.sleep(1)
  2715. child.send(123)
  2716. child.close()
  2717. conn = multiprocessing.connection.Client(address)
  2718. conn.send(456)
  2719. conn.close()
  2720. def test_timeout(self):
  2721. old_timeout = socket.getdefaulttimeout()
  2722. try:
  2723. socket.setdefaulttimeout(0.1)
  2724. parent, child = multiprocessing.Pipe(duplex=True)
  2725. l = multiprocessing.connection.Listener(family='AF_INET')
  2726. p = multiprocessing.Process(target=self._test_timeout,
  2727. args=(child, l.address))
  2728. p.start()
  2729. child.close()
  2730. self.assertEqual(parent.recv(), 123)
  2731. parent.close()
  2732. conn = l.accept()
  2733. self.assertEqual(conn.recv(), 456)
  2734. conn.close()
  2735. l.close()
  2736. p.join(10)
  2737. finally:
  2738. socket.setdefaulttimeout(old_timeout)
  2739. #
  2740. # Test what happens with no "if __name__ == '__main__'"
  2741. #
  2742. class TestNoForkBomb(unittest.TestCase):
  2743. def test_noforkbomb(self):
  2744. sm = multiprocessing.get_start_method()
  2745. name = os.path.join(os.path.dirname(__file__), 'mp_fork_bomb.py')
  2746. if sm != 'fork':
  2747. rc, out, err = test.script_helper.assert_python_failure(name, sm)
  2748. self.assertEqual('', out.decode('ascii'))
  2749. self.assertIn('RuntimeError', err.decode('ascii'))
  2750. else:
  2751. rc, out, err = test.script_helper.assert_python_ok(name, sm)
  2752. self.assertEqual('123', out.decode('ascii').rstrip())
  2753. self.assertEqual('', err.decode('ascii'))
  2754. #
  2755. # Issue #17555: ForkAwareThreadLock
  2756. #
  2757. class TestForkAwareThreadLock(unittest.TestCase):
  2758. # We recurisvely start processes. Issue #17555 meant that the
  2759. # after fork registry would get duplicate entries for the same
  2760. # lock. The size of the registry at generation n was ~2**n.
  2761. @classmethod
  2762. def child(cls, n, conn):
  2763. if n > 1:
  2764. p = multiprocessing.Process(target=cls.child, args=(n-1, conn))
  2765. p.start()
  2766. conn.close()
  2767. p.join(timeout=5)
  2768. else:
  2769. conn.send(len(util._afterfork_registry))
  2770. conn.close()
  2771. def test_lock(self):
  2772. r, w = multiprocessing.Pipe(False)
  2773. l = util.ForkAwareThreadLock()
  2774. old_size = len(util._afterfork_registry)
  2775. p = multiprocessing.Process(target=self.child, args=(5, w))
  2776. p.start()
  2777. w.close()
  2778. new_size = r.recv()
  2779. p.join(timeout=5)
  2780. self.assertLessEqual(new_size, old_size)
  2781. #
  2782. # Check that non-forked child processes do not inherit unneeded fds/handles
  2783. #
  2784. class TestCloseFds(unittest.TestCase):
  2785. def get_high_socket_fd(self):
  2786. if WIN32:
  2787. # The child process will not have any socket handles, so
  2788. # calling socket.fromfd() should produce WSAENOTSOCK even
  2789. # if there is a handle of the same number.
  2790. return socket.socket().detach()
  2791. else:
  2792. # We want to produce a socket with an fd high enough that a
  2793. # freshly created child process will not have any fds as high.
  2794. fd = socket.socket().detach()
  2795. to_close = []
  2796. while fd < 50:
  2797. to_close.append(fd)
  2798. fd = os.dup(fd)
  2799. for x in to_close:
  2800. os.close(x)
  2801. return fd
  2802. def close(self, fd):
  2803. if WIN32:
  2804. socket.socket(fileno=fd).close()
  2805. else:
  2806. os.close(fd)
  2807. @classmethod
  2808. def _test_closefds(cls, conn, fd):
  2809. try:
  2810. s = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
  2811. except Exception as e:
  2812. conn.send(e)
  2813. else:
  2814. s.close()
  2815. conn.send(None)
  2816. def test_closefd(self):
  2817. if not HAS_REDUCTION:
  2818. raise unittest.SkipTest('requires fd pickling')
  2819. reader, writer = multiprocessing.Pipe()
  2820. fd = self.get_high_socket_fd()
  2821. try:
  2822. p = multiprocessing.Process(target=self._test_closefds,
  2823. args=(writer, fd))
  2824. p.start()
  2825. writer.close()
  2826. e = reader.recv()
  2827. p.join(timeout=5)
  2828. finally:
  2829. self.close(fd)
  2830. writer.close()
  2831. reader.close()
  2832. if multiprocessing.get_start_method() == 'fork':
  2833. self.assertIs(e, None)
  2834. else:
  2835. WSAENOTSOCK = 10038
  2836. self.assertIsInstance(e, OSError)
  2837. self.assertTrue(e.errno == errno.EBADF or
  2838. e.winerror == WSAENOTSOCK, e)
  2839. #
  2840. # Issue #17097: EINTR should be ignored by recv(), send(), accept() etc
  2841. #
  2842. class TestIgnoreEINTR(unittest.TestCase):
  2843. @classmethod
  2844. def _test_ignore(cls, conn):
  2845. def handler(signum, frame):
  2846. pass
  2847. signal.signal(signal.SIGUSR1, handler)
  2848. conn.send('ready')
  2849. x = conn.recv()
  2850. conn.send(x)
  2851. conn.send_bytes(b'x'*(1024*1024)) # sending 1 MB should block
  2852. @unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1')
  2853. def test_ignore(self):
  2854. conn, child_conn = multiprocessing.Pipe()
  2855. try:
  2856. p = multiprocessing.Process(target=self._test_ignore,
  2857. args=(child_conn,))
  2858. p.daemon = True
  2859. p.start()
  2860. child_conn.close()
  2861. self.assertEqual(conn.recv(), 'ready')
  2862. time.sleep(0.1)
  2863. os.kill(p.pid, signal.SIGUSR1)
  2864. time.sleep(0.1)
  2865. conn.send(1234)
  2866. self.assertEqual(conn.recv(), 1234)
  2867. time.sleep(0.1)
  2868. os.kill(p.pid, signal.SIGUSR1)
  2869. self.assertEqual(conn.recv_bytes(), b'x'*(1024*1024))
  2870. time.sleep(0.1)
  2871. p.join()
  2872. finally:
  2873. conn.close()
  2874. @classmethod
  2875. def _test_ignore_listener(cls, conn):
  2876. def handler(signum, frame):
  2877. pass
  2878. signal.signal(signal.SIGUSR1, handler)
  2879. with multiprocessing.connection.Listener() as l:
  2880. conn.send(l.address)
  2881. a = l.accept()
  2882. a.send('welcome')
  2883. @unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1')
  2884. def test_ignore_listener(self):
  2885. conn, child_conn = multiprocessing.Pipe()
  2886. try:
  2887. p = multiprocessing.Process(target=self._test_ignore_listener,
  2888. args=(child_conn,))
  2889. p.daemon = True
  2890. p.start()
  2891. child_conn.close()
  2892. address = conn.recv()
  2893. time.sleep(0.1)
  2894. os.kill(p.pid, signal.SIGUSR1)
  2895. time.sleep(0.1)
  2896. client = multiprocessing.connection.Client(address)
  2897. self.assertEqual(client.recv(), 'welcome')
  2898. p.join()
  2899. finally:
  2900. conn.close()
  2901. class TestStartMethod(unittest.TestCase):
  2902. @classmethod
  2903. def _check_context(cls, conn):
  2904. conn.send(multiprocessing.get_start_method())
  2905. def check_context(self, ctx):
  2906. r, w = ctx.Pipe(duplex=False)
  2907. p = ctx.Process(target=self._check_context, args=(w,))
  2908. p.start()
  2909. w.close()
  2910. child_method = r.recv()
  2911. r.close()
  2912. p.join()
  2913. self.assertEqual(child_method, ctx.get_start_method())
  2914. def test_context(self):
  2915. for method in ('fork', 'spawn', 'forkserver'):
  2916. try:
  2917. ctx = multiprocessing.get_context(method)
  2918. except ValueError:
  2919. continue
  2920. self.assertEqual(ctx.get_start_method(), method)
  2921. self.assertIs(ctx.get_context(), ctx)
  2922. self.assertRaises(ValueError, ctx.set_start_method, 'spawn')
  2923. self.assertRaises(ValueError, ctx.set_start_method, None)
  2924. self.check_context(ctx)
  2925. def test_set_get(self):
  2926. multiprocessing.set_forkserver_preload(PRELOAD)
  2927. count = 0
  2928. old_method = multiprocessing.get_start_method()
  2929. try:
  2930. for method in ('fork', 'spawn', 'forkserver'):
  2931. try:
  2932. multiprocessing.set_start_method(method, force=True)
  2933. except ValueError:
  2934. continue
  2935. self.assertEqual(multiprocessing.get_start_method(), method)
  2936. ctx = multiprocessing.get_context()
  2937. self.assertEqual(ctx.get_start_method(), method)
  2938. self.assertTrue(type(ctx).__name__.lower().startswith(method))
  2939. self.assertTrue(
  2940. ctx.Process.__name__.lower().startswith(method))
  2941. self.check_context(multiprocessing)
  2942. count += 1
  2943. finally:
  2944. multiprocessing.set_start_method(old_method, force=True)
  2945. self.assertGreaterEqual(count, 1)
  2946. def test_get_all(self):
  2947. methods = multiprocessing.get_all_start_methods()
  2948. if sys.platform == 'win32':
  2949. self.assertEqual(methods, ['spawn'])
  2950. else:
  2951. self.assertTrue(methods == ['fork', 'spawn'] or
  2952. methods == ['fork', 'spawn', 'forkserver'])
  2953. #
  2954. # Check that killing process does not leak named semaphores
  2955. #
  2956. @unittest.skipIf(sys.platform == "win32",
  2957. "test semantics don't make sense on Windows")
  2958. class TestSemaphoreTracker(unittest.TestCase):
  2959. def test_semaphore_tracker(self):
  2960. import subprocess
  2961. cmd = '''if 1:
  2962. import multiprocessing as mp, time, os
  2963. mp.set_start_method("spawn")
  2964. lock1 = mp.Lock()
  2965. lock2 = mp.Lock()
  2966. os.write(%d, lock1._semlock.name.encode("ascii") + b"\\n")
  2967. os.write(%d, lock2._semlock.name.encode("ascii") + b"\\n")
  2968. time.sleep(10)
  2969. '''
  2970. r, w = os.pipe()
  2971. p = subprocess.Popen([sys.executable,
  2972. '-c', cmd % (w, w)],
  2973. pass_fds=[w],
  2974. stderr=subprocess.PIPE)
  2975. os.close(w)
  2976. with open(r, 'rb', closefd=True) as f:
  2977. name1 = f.readline().rstrip().decode('ascii')
  2978. name2 = f.readline().rstrip().decode('ascii')
  2979. _multiprocessing.sem_unlink(name1)
  2980. p.terminate()
  2981. p.wait()
  2982. time.sleep(1.0)
  2983. with self.assertRaises(OSError) as ctx:
  2984. _multiprocessing.sem_unlink(name2)
  2985. # docs say it should be ENOENT, but OSX seems to give EINVAL
  2986. self.assertIn(ctx.exception.errno, (errno.ENOENT, errno.EINVAL))
  2987. err = p.stderr.read().decode('utf-8')
  2988. p.stderr.close()
  2989. expected = 'semaphore_tracker: There appear to be 2 leaked semaphores'
  2990. self.assertRegex(err, expected)
  2991. self.assertRegex(err, 'semaphore_tracker: %r: \[Errno' % name1)
  2992. #
  2993. # Mixins
  2994. #
  2995. class ProcessesMixin(object):
  2996. TYPE = 'processes'
  2997. Process = multiprocessing.Process
  2998. connection = multiprocessing.connection
  2999. current_process = staticmethod(multiprocessing.current_process)
  3000. active_children = staticmethod(multiprocessing.active_children)
  3001. Pool = staticmethod(multiprocessing.Pool)
  3002. Pipe = staticmethod(multiprocessing.Pipe)
  3003. Queue = staticmethod(multiprocessing.Queue)
  3004. JoinableQueue = staticmethod(multiprocessing.JoinableQueue)
  3005. Lock = staticmethod(multiprocessing.Lock)
  3006. RLock = staticmethod(multiprocessing.RLock)
  3007. Semaphore = staticmethod(multiprocessing.Semaphore)
  3008. BoundedSemaphore = staticmethod(multiprocessing.BoundedSemaphore)
  3009. Condition = staticmethod(multiprocessing.Condition)
  3010. Event = staticmethod(multiprocessing.Event)
  3011. Barrier = staticmethod(multiprocessing.Barrier)
  3012. Value = staticmethod(multiprocessing.Value)
  3013. Array = staticmethod(multiprocessing.Array)
  3014. RawValue = staticmethod(multiprocessing.RawValue)
  3015. RawArray = staticmethod(multiprocessing.RawArray)
  3016. class ManagerMixin(object):
  3017. TYPE = 'manager'
  3018. Process = multiprocessing.Process
  3019. Queue = property(operator.attrgetter('manager.Queue'))
  3020. JoinableQueue = property(operator.attrgetter('manager.JoinableQueue'))
  3021. Lock = property(operator.attrgetter('manager.Lock'))
  3022. RLock = property(operator.attrgetter('manager.RLock'))
  3023. Semaphore = property(operator.attrgetter('manager.Semaphore'))
  3024. BoundedSemaphore = property(operator.attrgetter('manager.BoundedSemaphore'))
  3025. Condition = property(operator.attrgetter('manager.Condition'))
  3026. Event = property(operator.attrgetter('manager.Event'))
  3027. Barrier = property(operator.attrgetter('manager.Barrier'))
  3028. Value = property(operator.attrgetter('manager.Value'))
  3029. Array = property(operator.attrgetter('manager.Array'))
  3030. list = property(operator.attrgetter('manager.list'))
  3031. dict = property(operator.attrgetter('manager.dict'))
  3032. Namespace = property(operator.attrgetter('manager.Namespace'))
  3033. @classmethod
  3034. def Pool(cls, *args, **kwds):
  3035. return cls.manager.Pool(*args, **kwds)
  3036. @classmethod
  3037. def setUpClass(cls):
  3038. cls.manager = multiprocessing.Manager()
  3039. @classmethod
  3040. def tearDownClass(cls):
  3041. # only the manager process should be returned by active_children()
  3042. # but this can take a bit on slow machines, so wait a few seconds
  3043. # if there are other children too (see #17395)
  3044. t = 0.01
  3045. while len(multiprocessing.active_children()) > 1 and t < 5:
  3046. time.sleep(t)
  3047. t *= 2
  3048. gc.collect() # do garbage collection
  3049. if cls.manager._number_of_objects() != 0:
  3050. # This is not really an error since some tests do not
  3051. # ensure that all processes which hold a reference to a
  3052. # managed object have been joined.
  3053. print('Shared objects which still exist at manager shutdown:')
  3054. print(cls.manager._debug_info())
  3055. cls.manager.shutdown()
  3056. cls.manager.join()
  3057. cls.manager = None
  3058. class ThreadsMixin(object):
  3059. TYPE = 'threads'
  3060. Process = multiprocessing.dummy.Process
  3061. connection = multiprocessing.dummy.connection
  3062. current_process = staticmethod(multiprocessing.dummy.current_process)
  3063. active_children = staticmethod(multiprocessing.dummy.active_children)
  3064. Pool = staticmethod(multiprocessing.Pool)
  3065. Pipe = staticmethod(multiprocessing.dummy.Pipe)
  3066. Queue = staticmethod(multiprocessing.dummy.Queue)
  3067. JoinableQueue = staticmethod(multiprocessing.dummy.JoinableQueue)
  3068. Lock = staticmethod(multiprocessing.dummy.Lock)
  3069. RLock = staticmethod(multiprocessing.dummy.RLock)
  3070. Semaphore = staticmethod(multiprocessing.dummy.Semaphore)
  3071. BoundedSemaphore = staticmethod(multiprocessing.dummy.BoundedSemaphore)
  3072. Condition = staticmethod(multiprocessing.dummy.Condition)
  3073. Event = staticmethod(multiprocessing.dummy.Event)
  3074. Barrier = staticmethod(multiprocessing.dummy.Barrier)
  3075. Value = staticmethod(multiprocessing.dummy.Value)
  3076. Array = staticmethod(multiprocessing.dummy.Array)
  3077. #
  3078. # Functions used to create test cases from the base ones in this module
  3079. #
  3080. def install_tests_in_module_dict(remote_globs, start_method):
  3081. __module__ = remote_globs['__name__']
  3082. local_globs = globals()
  3083. ALL_TYPES = {'processes', 'threads', 'manager'}
  3084. for name, base in local_globs.items():
  3085. if not isinstance(base, type):
  3086. continue
  3087. if issubclass(base, BaseTestCase):
  3088. if base is BaseTestCase:
  3089. continue
  3090. assert set(base.ALLOWED_TYPES) <= ALL_TYPES, base.ALLOWED_TYPES
  3091. for type_ in base.ALLOWED_TYPES:
  3092. newname = 'With' + type_.capitalize() + name[1:]
  3093. Mixin = local_globs[type_.capitalize() + 'Mixin']
  3094. class Temp(base, Mixin, unittest.TestCase):
  3095. pass
  3096. Temp.__name__ = Temp.__qualname__ = newname
  3097. Temp.__module__ = __module__
  3098. remote_globs[newname] = Temp
  3099. elif issubclass(base, unittest.TestCase):
  3100. class Temp(base, object):
  3101. pass
  3102. Temp.__name__ = Temp.__qualname__ = name
  3103. Temp.__module__ = __module__
  3104. remote_globs[name] = Temp
  3105. dangling = [None, None]
  3106. old_start_method = [None]
  3107. def setUpModule():
  3108. multiprocessing.set_forkserver_preload(PRELOAD)
  3109. multiprocessing.process._cleanup()
  3110. dangling[0] = multiprocessing.process._dangling.copy()
  3111. dangling[1] = threading._dangling.copy()
  3112. old_start_method[0] = multiprocessing.get_start_method(allow_none=True)
  3113. try:
  3114. multiprocessing.set_start_method(start_method, force=True)
  3115. except ValueError:
  3116. raise unittest.SkipTest(start_method +
  3117. ' start method not supported')
  3118. if sys.platform.startswith("linux"):
  3119. try:
  3120. lock = multiprocessing.RLock()
  3121. except OSError:
  3122. raise unittest.SkipTest("OSError raises on RLock creation, "
  3123. "see issue 3111!")
  3124. check_enough_semaphores()
  3125. util.get_temp_dir() # creates temp directory
  3126. multiprocessing.get_logger().setLevel(LOG_LEVEL)
  3127. def tearDownModule():
  3128. multiprocessing.set_start_method(old_start_method[0], force=True)
  3129. # pause a bit so we don't get warning about dangling threads/processes
  3130. time.sleep(0.5)
  3131. multiprocessing.process._cleanup()
  3132. gc.collect()
  3133. tmp = set(multiprocessing.process._dangling) - set(dangling[0])
  3134. if tmp:
  3135. print('Dangling processes:', tmp, file=sys.stderr)
  3136. del tmp
  3137. tmp = set(threading._dangling) - set(dangling[1])
  3138. if tmp:
  3139. print('Dangling threads:', tmp, file=sys.stderr)
  3140. remote_globs['setUpModule'] = setUpModule
  3141. remote_globs['tearDownModule'] = tearDownModule