2222from multiprocessing .connection import Pipe
2323from multiprocessing .synchronize import Lock , BoundedSemaphore , Semaphore , Condition
2424from multiprocessing .util import debug , info , Finalize , register_after_fork
25- from multiprocessing .forking import assert_spawning
25+ from multiprocessing .forking import assert_spawning , ForkingPickler
2626
2727#
2828# Queue type using a pipe, buffer and thread
@@ -69,8 +69,8 @@ def _after_fork(self):
6969 self ._joincancelled = False
7070 self ._closed = False
7171 self ._close = None
72- self ._send = self ._writer .send
73- self ._recv = self ._reader .recv
72+ self ._send_bytes = self ._writer .send_bytes
73+ self ._recv_bytes = self ._reader .recv_bytes
7474 self ._poll = self ._reader .poll
7575
7676 def put (self , obj , block = True , timeout = None ):
@@ -89,14 +89,9 @@ def put(self, obj, block=True, timeout=None):
8989
9090 def get (self , block = True , timeout = None ):
9191 if block and timeout is None :
92- self ._rlock .acquire ()
93- try :
94- res = self ._recv ()
95- self ._sem .release ()
96- return res
97- finally :
98- self ._rlock .release ()
99-
92+ with self ._rlock :
93+ res = self ._recv_bytes ()
94+ self ._sem .release ()
10095 else :
10196 if block :
10297 deadline = time .time () + timeout
@@ -109,11 +104,12 @@ def get(self, block=True, timeout=None):
109104 raise Empty
110105 elif not self ._poll ():
111106 raise Empty
112- res = self ._recv ()
107+ res = self ._recv_bytes ()
113108 self ._sem .release ()
114- return res
115109 finally :
116110 self ._rlock .release ()
111+ # unserialize the data after having released the lock
112+ return ForkingPickler .loads (res )
117113
118114 def qsize (self ):
119115 # Raises NotImplementedError on Mac OSX because of broken sem_getvalue()
@@ -158,7 +154,7 @@ def _start_thread(self):
158154 self ._buffer .clear ()
159155 self ._thread = threading .Thread (
160156 target = Queue ._feed ,
161- args = (self ._buffer , self ._notempty , self ._send ,
157+ args = (self ._buffer , self ._notempty , self ._send_bytes ,
162158 self ._wlock , self ._writer .close , self ._ignore_epipe ),
163159 name = 'QueueFeederThread'
164160 )
@@ -210,7 +206,7 @@ def _finalize_close(buffer, notempty):
210206 notempty .release ()
211207
212208 @staticmethod
213- def _feed (buffer , notempty , send , writelock , close , ignore_epipe ):
209+ def _feed (buffer , notempty , send_bytes , writelock , close , ignore_epipe ):
214210 debug ('starting thread to feed data to pipe' )
215211 from .util import is_exiting
216212
@@ -241,16 +237,14 @@ def _feed(buffer, notempty, send, writelock, close, ignore_epipe):
241237 close ()
242238 return
243239
240+ # serialize the data before acquiring the lock
241+ obj = ForkingPickler .dumps (obj )
244242 if wacquire is None :
245- send (obj )
246- # Delete references to object. See issue16284
247- del obj
243+ send_bytes (obj )
248244 else :
249245 wacquire ()
250246 try :
251- send (obj )
252- # Delete references to object. See issue16284
253- del obj
247+ send_bytes (obj )
254248 finally :
255249 wrelease ()
256250 except IndexError :
@@ -344,7 +338,6 @@ def __init__(self):
344338 self ._wlock = None
345339 else :
346340 self ._wlock = Lock ()
347- self ._make_methods ()
348341
349342 def empty (self ):
350343 return not self ._poll ()
@@ -355,29 +348,19 @@ def __getstate__(self):
355348
356349 def __setstate__ (self , state ):
357350 (self ._reader , self ._writer , self ._rlock , self ._wlock ) = state
358- self ._make_methods ()
359351
360- def _make_methods (self ):
361- recv = self ._reader .recv
362- racquire , rrelease = self ._rlock .acquire , self ._rlock .release
363- def get ():
364- racquire ()
365- try :
366- return recv ()
367- finally :
368- rrelease ()
369- self .get = get
352+ def get (self ):
353+ with self ._rlock :
354+ res = self ._reader .recv_bytes ()
355+ # unserialize the data after having released the lock
356+ return ForkingPickler .loads (res )
370357
358+ def put (self , obj ):
359+ # serialize the data before acquiring the lock
360+ obj = ForkingPickler .dumps (obj )
371361 if self ._wlock is None :
372362 # writes to a message oriented win32 pipe are atomic
373- self .put = self . _writer .send
363+ self ._writer .send_bytes ( obj )
374364 else :
375- send = self ._writer .send
376- wacquire , wrelease = self ._wlock .acquire , self ._wlock .release
377- def put (obj ):
378- wacquire ()
379- try :
380- return send (obj )
381- finally :
382- wrelease ()
383- self .put = put
365+ with self ._wlock :
366+ self ._writer .send_bytes (obj )
0 commit comments