@@ -184,6 +184,7 @@ def __init__(self): # type: () -> None
184
184
self .threads = set () # type: Set[threading.Thread]
185
185
self .exceptions = [] # type: List[WorkflowException]
186
186
self .pending_jobs = [] # type: List[JobBase]
187
+ self .pending_jobs_lock = threading .Lock ()
187
188
188
189
self .max_ram = psutil .virtual_memory ().available / 2 ** 20
189
190
self .max_cores = psutil .cpu_count ()
@@ -217,43 +218,48 @@ def run_job(self,
217
218
""" Execute a single Job in a seperate thread. """
218
219
219
220
if job is not None :
220
- self .pending_jobs .append (job )
221
+ with self .pending_jobs_lock :
222
+ self .pending_jobs .append (job )
221
223
222
224
while self .pending_jobs :
223
- job = self .pending_jobs [0 ]
224
- if isinstance (job , JobBase ):
225
- if ((self .allocated_ram + job .builder .resources ["ram" ]) > self .max_ram or
226
- (self .allocated_cores + job .builder .resources ["cores" ]) > self .max_cores ):
227
- return
228
-
229
- self .pending_jobs .pop (0 )
230
-
231
- def runner ():
225
+ with self .pending_jobs_lock :
226
+ job = self .pending_jobs [0 ]
227
+ if isinstance (job , JobBase ):
228
+ if ((self .allocated_ram + job .builder .resources ["ram" ])
229
+ > self .max_ram or
230
+ (self .allocated_cores + job .builder .resources ["cores" ])
231
+ > self .max_cores ):
232
+ return
233
+ self .pending_jobs .remove (job )
234
+
235
+ def runner (my_job , my_runtime_context ):
232
236
""" Job running thread. """
233
237
try :
234
- job .run (runtime_context )
238
+ my_job .run (my_runtime_context )
235
239
except WorkflowException as err :
236
240
_logger .exception ("Got workflow error" )
237
241
self .exceptions .append (err )
238
242
except Exception as err : # pylint: disable=broad-except
239
243
_logger .exception ("Got workflow error" )
240
244
self .exceptions .append (WorkflowException (Text (err )))
241
245
finally :
242
- with runtime_context .workflow_eval_lock :
243
- self .threads .remove (thread )
244
- if isinstance (job , JobBase ):
245
- self .allocated_ram -= job .builder .resources ["ram" ]
246
- self .allocated_cores -= job .builder .resources ["cores" ]
247
- runtime_context .workflow_eval_lock .notifyAll ()
248
-
249
- thread = threading .Thread (target = runner )
246
+ with my_runtime_context .workflow_eval_lock :
247
+ self .threads .remove (threading .current_thread ())
248
+ if isinstance (my_job , JobBase ):
249
+ self .allocated_ram -= my_job .builder .resources ["ram" ]
250
+ self .allocated_cores -= my_job .builder .resources ["cores" ]
251
+ my_runtime_context .workflow_eval_lock .notifyAll ()
252
+
253
+ thread = threading .Thread (
254
+ target = runner , args = (job , runtime_context ))
250
255
thread .daemon = True
251
256
self .threads .add (thread )
252
257
if isinstance (job , JobBase ):
253
258
self .allocated_ram += job .builder .resources ["ram" ]
254
259
self .allocated_cores += job .builder .resources ["cores" ]
255
260
thread .start ()
256
261
262
+
257
263
def wait_for_next_completion (self , runtimeContext ): # type: (RuntimeContext) -> None
258
264
""" Wait for jobs to finish. """
259
265
if runtimeContext .workflow_eval_lock is not None :
@@ -294,3 +300,4 @@ def run_jobs(self,
294
300
295
301
while self .threads :
296
302
self .wait_for_next_completion (runtime_context )
303
+ runtime_context .workflow_eval_lock .release ()
0 commit comments