17
17
import socket
18
18
import random
19
19
import logging
20
+ import subprocess
20
21
import struct
21
22
import operator
22
23
import pickle
@@ -3765,6 +3766,27 @@ def test_shared_memory_SharedMemoryServer_ignores_sigint(self):
3765
3766
3766
3767
smm .shutdown ()
3767
3768
3769
+ @unittest .skipIf (os .name != "posix" , "resource_tracker is posix only" )
3770
+ def test_shared_memory_SharedMemoryManager_reuses_resource_tracker (self ):
3771
+ # bpo-36867: test that a SharedMemoryManager uses the
3772
+ # same resource_tracker process as its parent.
3773
+ cmd = '''if 1:
3774
+ from multiprocessing.managers import SharedMemoryManager
3775
+
3776
+
3777
+ smm = SharedMemoryManager()
3778
+ smm.start()
3779
+ sl = smm.ShareableList(range(10))
3780
+ smm.shutdown()
3781
+ '''
3782
+ rc , out , err = test .support .script_helper .assert_python_ok ('-c' , cmd )
3783
+
3784
+ # Before bpo-36867 was fixed, a SharedMemoryManager not using the same
3785
+ # resource_tracker process as its parent would make the parent's
3786
+ # tracker complain about sl being leaked even though smm.shutdown()
3787
+ # properly released sl.
3788
+ self .assertFalse (err )
3789
+
3768
3790
def test_shared_memory_SharedMemoryManager_basics (self ):
3769
3791
smm1 = multiprocessing .managers .SharedMemoryManager ()
3770
3792
with self .assertRaises (ValueError ):
@@ -3904,8 +3926,6 @@ def test_shared_memory_ShareableList_pickling(self):
3904
3926
sl .shm .close ()
3905
3927
3906
3928
def test_shared_memory_cleaned_after_process_termination (self ):
3907
- import subprocess
3908
- from multiprocessing import shared_memory
3909
3929
cmd = '''if 1:
3910
3930
import os, time, sys
3911
3931
from multiprocessing import shared_memory
@@ -3916,18 +3936,29 @@ def test_shared_memory_cleaned_after_process_termination(self):
3916
3936
sys.stdout.flush()
3917
3937
time.sleep(100)
3918
3938
'''
3919
- p = subprocess .Popen ([sys .executable , '-E' , '-c' , cmd ],
3920
- stdout = subprocess .PIPE )
3921
- name = p .stdout .readline ().strip ().decode ()
3939
+ with subprocess .Popen ([sys .executable , '-E' , '-c' , cmd ],
3940
+ stdout = subprocess .PIPE ,
3941
+ stderr = subprocess .PIPE ) as p :
3942
+ name = p .stdout .readline ().strip ().decode ()
3922
3943
3923
- # killing abruptly processes holding reference to a shared memory
3924
- # segment should not leak the given memory segment.
3925
- p .terminate ()
3926
- p .wait ()
3927
- time .sleep (1.0 ) # wait for the OS to collect the segment
3944
+ # killing abruptly processes holding reference to a shared memory
3945
+ # segment should not leak the given memory segment.
3946
+ p .terminate ()
3947
+ p .wait ()
3948
+ time .sleep (1.0 ) # wait for the OS to collect the segment
3928
3949
3929
- with self .assertRaises (FileNotFoundError ):
3930
- smm = shared_memory .SharedMemory (name , create = False )
3950
+ # The shared memory file was deleted.
3951
+ with self .assertRaises (FileNotFoundError ):
3952
+ smm = shared_memory .SharedMemory (name , create = False )
3953
+
3954
+ if os .name == 'posix' :
3955
+ # A warning was emitted by the subprocess' own
3956
+ # resource_tracker (on Windows, shared memory segments
3957
+ # are released automatically by the OS).
3958
+ err = p .stderr .read ().decode ()
3959
+ self .assertIn (
3960
+ "resource_tracker: There appear to be 1 leaked "
3961
+ "shared_memory objects to clean up at shutdown" , err )
3931
3962
3932
3963
#
3933
3964
#
@@ -4560,7 +4591,7 @@ def run_in_child(cls):
4560
4591
print (json .dumps (flags ))
4561
4592
4562
4593
def test_flags (self ):
4563
- import json , subprocess
4594
+ import json
4564
4595
# start child process using unusual flags
4565
4596
prog = ('from test._test_multiprocessing import TestFlags; ' +
4566
4597
'TestFlags.run_in_child()' )
@@ -4866,7 +4897,6 @@ def test_resource_tracker(self):
4866
4897
#
4867
4898
# Check that killing process does not leak named semaphores
4868
4899
#
4869
- import subprocess
4870
4900
cmd = '''if 1:
4871
4901
import time, os, tempfile
4872
4902
import multiprocessing as mp
0 commit comments