26
26
PENDING , RUNNING , CANCELLED , CANCELLED_AND_NOTIFIED , FINISHED , Future ,
27
27
BrokenExecutor )
28
28
from concurrent .futures .process import BrokenProcessPool , _check_system_limits
29
- from multiprocessing import get_context
30
29
31
30
import multiprocessing .process
32
31
import multiprocessing .util
32
+ import multiprocessing as mp
33
33
34
34
35
35
if support .check_sanitizer (address = True , memory = True ):
@@ -131,7 +131,6 @@ def setUp(self):
131
131
self .executor = self .executor_type (
132
132
max_workers = self .worker_count ,
133
133
** self .executor_kwargs )
134
- self ._prime_executor ()
135
134
136
135
def tearDown (self ):
137
136
self .executor .shutdown (wait = True )
@@ -145,15 +144,7 @@ def tearDown(self):
145
144
super ().tearDown ()
146
145
147
146
def get_context (self ):
148
- return get_context (self .ctx )
149
-
150
- def _prime_executor (self ):
151
- # Make sure that the executor is ready to do work before running the
152
- # tests. This should reduce the probability of timeouts in the tests.
153
- futures = [self .executor .submit (time .sleep , 0.1 )
154
- for _ in range (self .worker_count )]
155
- for f in futures :
156
- f .result ()
147
+ return mp .get_context (self .ctx )
157
148
158
149
159
150
class ThreadPoolMixin (ExecutorMixin ):
@@ -276,9 +267,6 @@ def test_initializer(self):
276
267
with self .assertRaises (BrokenExecutor ):
277
268
self .executor .submit (get_init_status )
278
269
279
- def _prime_executor (self ):
280
- pass
281
-
282
270
@contextlib .contextmanager
283
271
def _assert_logged (self , msg ):
284
272
if self .log_queue is not None :
@@ -365,14 +353,14 @@ def test_hang_issue12364(self):
365
353
f .result ()
366
354
367
355
def test_cancel_futures (self ):
368
- executor = self .executor_type ( max_workers = 3 )
369
- fs = [executor .submit (time .sleep , .1 ) for _ in range (50 )]
370
- executor .shutdown (cancel_futures = True )
356
+ assert self .worker_count <= 5 , "test needs few workers"
357
+ fs = [self . executor .submit (time .sleep , .1 ) for _ in range (50 )]
358
+ self . executor .shutdown (cancel_futures = True )
371
359
# We can't guarantee the exact number of cancellations, but we can
372
- # guarantee that *some* were cancelled. With setting max_workers to 3,
373
- # most of the submitted futures should have been cancelled.
360
+ # guarantee that *some* were cancelled. With few workers, many of
361
+ # the submitted futures should have been cancelled.
374
362
cancelled = [fut for fut in fs if fut .cancelled ()]
375
- self .assertTrue (len (cancelled ) >= 35 , msg = f" { len ( cancelled ) = } " )
363
+ self .assertGreater (len (cancelled ), 20 )
376
364
377
365
# Ensure the other futures were able to finish.
378
366
# Use "not fut.cancelled()" instead of "fut.done()" to include futures
@@ -385,33 +373,32 @@ def test_cancel_futures(self):
385
373
# Similar to the number of cancelled futures, we can't guarantee the
386
374
# exact number that completed. But, we can guarantee that at least
387
375
# one finished.
388
- self .assertTrue (len (others ) > 0 , msg = f" { len ( others ) = } " )
376
+ self .assertGreater (len (others ), 0 )
389
377
390
- def test_hang_issue39205 (self ):
378
+ def test_hang_gh83386 (self ):
391
379
"""shutdown(wait=False) doesn't hang at exit with running futures.
392
380
393
- See https://bugs. python.org/issue39205 .
381
+ See https://github.com/ python/cpython/issues/83386 .
394
382
"""
395
383
if self .executor_type == futures .ProcessPoolExecutor :
396
384
raise unittest .SkipTest (
397
- "Hangs due to https://bugs. python.org/issue39205 " )
385
+ "Hangs, see https://github.com/ python/cpython/issues/83386 " )
398
386
399
387
rc , out , err = assert_python_ok ('-c' , """if True:
400
388
from concurrent.futures import {executor_type}
401
389
from test.test_concurrent_futures import sleep_and_print
402
390
if __name__ == "__main__":
391
+ if {context!r}: multiprocessing.set_start_method({context!r})
403
392
t = {executor_type}(max_workers=3)
404
393
t.submit(sleep_and_print, 1.0, "apple")
405
394
t.shutdown(wait=False)
406
- """ .format (executor_type = self .executor_type .__name__ ))
395
+ """ .format (executor_type = self .executor_type .__name__ ,
396
+ context = getattr (self , 'ctx' , None )))
407
397
self .assertFalse (err )
408
398
self .assertEqual (out .strip (), b"apple" )
409
399
410
400
411
401
class ThreadPoolShutdownTest (ThreadPoolMixin , ExecutorShutdownTest , BaseTestCase ):
412
- def _prime_executor (self ):
413
- pass
414
-
415
402
def test_threads_terminate (self ):
416
403
def acquire_lock (lock ):
417
404
lock .acquire ()
@@ -506,14 +493,11 @@ def test_cancel_futures_wait_false(self):
506
493
507
494
508
495
class ProcessPoolShutdownTest (ExecutorShutdownTest ):
509
- def _prime_executor (self ):
510
- pass
511
-
512
496
def test_processes_terminate (self ):
513
497
def acquire_lock (lock ):
514
498
lock .acquire ()
515
499
516
- mp_context = get_context ()
500
+ mp_context = self . get_context ()
517
501
sem = mp_context .Semaphore (0 )
518
502
for _ in range (3 ):
519
503
self .executor .submit (acquire_lock , sem )
@@ -527,7 +511,8 @@ def acquire_lock(lock):
527
511
p .join ()
528
512
529
513
def test_context_manager_shutdown (self ):
530
- with futures .ProcessPoolExecutor (max_workers = 5 ) as e :
514
+ with futures .ProcessPoolExecutor (
515
+ max_workers = 5 , mp_context = self .get_context ()) as e :
531
516
processes = e ._processes
532
517
self .assertEqual (list (e .map (abs , range (- 5 , 5 ))),
533
518
[5 , 4 , 3 , 2 , 1 , 0 , 1 , 2 , 3 , 4 ])
@@ -536,7 +521,8 @@ def test_context_manager_shutdown(self):
536
521
p .join ()
537
522
538
523
def test_del_shutdown (self ):
539
- executor = futures .ProcessPoolExecutor (max_workers = 5 )
524
+ executor = futures .ProcessPoolExecutor (
525
+ max_workers = 5 , mp_context = self .get_context ())
540
526
res = executor .map (abs , range (- 5 , 5 ))
541
527
executor_manager_thread = executor ._executor_manager_thread
542
528
processes = executor ._processes
@@ -559,7 +545,8 @@ def test_del_shutdown(self):
559
545
def test_shutdown_no_wait (self ):
560
546
# Ensure that the executor cleans up the processes when calling
561
547
# shutdown with wait=False
562
- executor = futures .ProcessPoolExecutor (max_workers = 5 )
548
+ executor = futures .ProcessPoolExecutor (
549
+ max_workers = 5 , mp_context = self .get_context ())
563
550
res = executor .map (abs , range (- 5 , 5 ))
564
551
processes = executor ._processes
565
552
call_queue = executor ._call_queue
@@ -936,7 +923,7 @@ def submit(pool):
936
923
pool .submit (submit , pool )
937
924
938
925
for _ in range (50 ):
939
- with futures .ProcessPoolExecutor (1 , mp_context = get_context ('fork' )) as workers :
926
+ with futures .ProcessPoolExecutor (1 , mp_context = mp . get_context ('fork' )) as workers :
940
927
workers .submit (tuple )
941
928
942
929
@@ -1006,7 +993,7 @@ def test_traceback(self):
1006
993
def test_ressources_gced_in_workers (self ):
1007
994
# Ensure that argument for a job are correctly gc-ed after the job
1008
995
# is finished
1009
- mgr = get_context ( self .ctx ).Manager ()
996
+ mgr = self .get_context ( ).Manager ()
1010
997
obj = EventfulGCObj (mgr )
1011
998
future = self .executor .submit (id , obj )
1012
999
future .result ()
@@ -1022,36 +1009,37 @@ def test_ressources_gced_in_workers(self):
1022
1009
mgr .join ()
1023
1010
1024
1011
def test_saturation (self ):
1025
- executor = self .executor_type ( 4 )
1026
- mp_context = get_context ()
1012
+ executor = self .executor
1013
+ mp_context = self . get_context ()
1027
1014
sem = mp_context .Semaphore (0 )
1028
1015
job_count = 15 * executor ._max_workers
1029
- try :
1030
- for _ in range (job_count ):
1031
- executor .submit (sem .acquire )
1032
- self .assertEqual (len (executor ._processes ), executor ._max_workers )
1033
- for _ in range (job_count ):
1034
- sem .release ()
1035
- finally :
1036
- executor .shutdown ()
1016
+ for _ in range (job_count ):
1017
+ executor .submit (sem .acquire )
1018
+ self .assertEqual (len (executor ._processes ), executor ._max_workers )
1019
+ for _ in range (job_count ):
1020
+ sem .release ()
1037
1021
1038
1022
def test_idle_process_reuse_one (self ):
1039
- executor = self .executor_type (4 )
1023
+ executor = self .executor
1024
+ assert executor ._max_workers >= 4
1040
1025
executor .submit (mul , 21 , 2 ).result ()
1041
1026
executor .submit (mul , 6 , 7 ).result ()
1042
1027
executor .submit (mul , 3 , 14 ).result ()
1043
1028
self .assertEqual (len (executor ._processes ), 1 )
1044
- executor .shutdown ()
1045
1029
1046
1030
def test_idle_process_reuse_multiple (self ):
1047
- executor = self .executor_type (4 )
1031
+ executor = self .executor
1032
+ assert executor ._max_workers <= 5
1048
1033
executor .submit (mul , 12 , 7 ).result ()
1049
1034
executor .submit (mul , 33 , 25 )
1050
1035
executor .submit (mul , 25 , 26 ).result ()
1051
1036
executor .submit (mul , 18 , 29 )
1052
- self .assertLessEqual (len (executor ._processes ), 2 )
1037
+ executor .submit (mul , 1 , 2 ).result ()
1038
+ executor .submit (mul , 0 , 9 )
1039
+ self .assertLessEqual (len (executor ._processes ), 3 )
1053
1040
executor .shutdown ()
1054
1041
1042
+
1055
1043
create_executor_tests (ProcessPoolExecutorTest ,
1056
1044
executor_mixins = (ProcessPoolForkMixin ,
1057
1045
ProcessPoolForkserverMixin ,
@@ -1153,7 +1141,7 @@ def _check_crash(self, error, func, *args, ignore_stderr=False):
1153
1141
self .executor .shutdown (wait = True )
1154
1142
1155
1143
executor = self .executor_type (
1156
- max_workers = 2 , mp_context = get_context ( self .ctx ))
1144
+ max_workers = 2 , mp_context = self .get_context ( ))
1157
1145
res = executor .submit (func , * args )
1158
1146
1159
1147
if ignore_stderr :
@@ -1232,7 +1220,7 @@ def test_shutdown_deadlock(self):
1232
1220
# if a worker fails after the shutdown call.
1233
1221
self .executor .shutdown (wait = True )
1234
1222
with self .executor_type (max_workers = 2 ,
1235
- mp_context = get_context ( self .ctx )) as executor :
1223
+ mp_context = self .get_context ( )) as executor :
1236
1224
self .executor = executor # Allow clean up in fail_on_deadlock
1237
1225
f = executor .submit (_crash , delay = .1 )
1238
1226
executor .shutdown (wait = True )
@@ -1245,7 +1233,7 @@ def test_shutdown_deadlock_pickle(self):
1245
1233
# Reported in bpo-39104.
1246
1234
self .executor .shutdown (wait = True )
1247
1235
with self .executor_type (max_workers = 2 ,
1248
- mp_context = get_context ( self .ctx )) as executor :
1236
+ mp_context = self .get_context ( )) as executor :
1249
1237
self .executor = executor # Allow clean up in fail_on_deadlock
1250
1238
1251
1239
# Start the executor and get the executor_manager_thread to collect
0 commit comments