@@ -72,7 +72,7 @@ class _SharedCache:
7272 def __init__ (self , constructor , destructor ):
7373 self ._constructor = constructor
7474 self ._destructor = destructor
75- self ._live_owners = set ()
75+ self ._live_owners = {}
7676 self ._cache = {}
7777 self ._lock = threading .Lock ()
7878 self ._counter = 0
@@ -82,10 +82,10 @@ def _next_id(self):
8282 self ._counter += 1
8383 return self ._counter
8484
85- def register (self ):
85+ def register (self , is_context = False ):
8686 with self ._lock :
8787 owner = self ._next_id ()
88- self ._live_owners . add ( owner )
88+ self ._live_owners [ owner ] = is_context
8989 return owner
9090
9191 def purge (self , owner ):
@@ -97,7 +97,7 @@ def purge(self, owner):
9797 "shutdown, the subprocess was already cleaned up earlier." ,
9898 owner )
9999 return
100- self ._live_owners . remove ( owner )
100+ del self ._live_owners [ owner ]
101101 for key , entry in list (self ._cache .items ()):
102102 if owner in entry .owners :
103103 entry .owners .remove (owner )
@@ -108,14 +108,23 @@ def purge(self, owner):
108108 for value in to_delete :
109109 self ._destructor (value )
110110
111- def get (self , * key ):
112- if not self ._live_owners :
113- raise RuntimeError ("At least one owner must be registered." )
111+ def get (self , * key , owner = None ):
114112 with self ._lock :
113+ if not self ._live_owners :
114+ raise RuntimeError ("At least one owner must be registered." )
115+ if owner is not None and owner not in self ._live_owners :
116+ raise RuntimeError ("The requesting owner must be registered." )
117+
115118 if key not in self ._cache :
116119 self ._cache [key ] = _SharedCacheEntry (self ._constructor (* key ), set ())
117- for owner in self . _live_owners :
120+ if owner is not None :
118121 self ._cache [key ].owners .add (owner )
122+ for live_owner , is_context in self ._live_owners .items ():
123+ if is_context :
124+ self ._cache [key ].owners .add (live_owner )
125+ else :
126+ for live_owner in self ._live_owners :
127+ self ._cache [key ].owners .add (live_owner )
119128 return self ._cache [key ].obj
120129
121130 def force_remove (self , * key ):
@@ -180,7 +189,7 @@ def cache_subprocesses(cls):
180189 These subprocesses may be shared with other contexts as well.
181190 """
182191 try :
183- unique_id = cls ._cache .register ()
192+ unique_id = cls ._cache .register (is_context = True )
184193 yield
185194 finally :
186195 cls ._cache .purge (unique_id )
@@ -214,7 +223,7 @@ def start(self):
214223 channel_ready = grpc .channel_ready_future (self ._grpc_channel )
215224 while True :
216225 if process is not None and process .poll () is not None :
217- _LOGGER .error ("Started job service with %s" , process .args )
226+ _LOGGER .error ("Failed to start job service with %s" , process .args )
218227 raise RuntimeError (
219228 'Service failed to start up with error %s' % process .poll ())
220229 try :
@@ -235,15 +244,16 @@ def start(self):
235244 def start_process (self ):
236245 if self ._owner_id is not None :
237246 self ._cache .purge (self ._owner_id )
238- self ._owner_id = self ._cache .register ()
239- return self ._cache .get (tuple (self ._cmd ), self ._port , self ._logger )
247+ self ._owner_id = self ._cache .register (is_context = False )
248+ return self ._cache .get (
249+ tuple (self ._cmd ), self ._port , self ._logger , owner = self ._owner_id )
240250
241251 def _really_start_process (cmd , port , logger ):
242252 if not port :
243253 port , = pick_port (None )
244254 cmd = [arg .replace ('{{PORT}}' , str (port )) for arg in cmd ] # pylint: disable=not-an-iterable
245255 endpoint = 'localhost:%s' % port
246- _LOGGER .info ( "Starting service with %s" , str ( cmd ). replace ( "'," , "'" ) )
256+ _LOGGER .warning ( "Really starting service at %s with cmd: %s" , endpoint , cmd )
247257 process = subprocess .Popen (
248258 cmd , stdout = subprocess .PIPE , stderr = subprocess .STDOUT )
249259
@@ -295,9 +305,11 @@ def stop_force(self):
295305 self ._grpc_channel = None
296306
297307 def _really_stop_process (process_and_endpoint ):
298- process , _ = process_and_endpoint # pylint: disable=unpacking-non-sequence
308+ process , endpoint = process_and_endpoint # pylint: disable=unpacking-non-sequence
299309 if not process :
300310 return
311+ _LOGGER .warning (
312+ "Really destroying service at %s with cmd: %s" , endpoint , process .args )
301313 for _ in range (5 ):
302314 if process .poll () is not None :
303315 break
0 commit comments