6060 provisionEndpoint = flag .String ("provision_endpoint" , "" , "Provision endpoint (required)." )
6161 controlEndpoint = flag .String ("control_endpoint" , "" , "Control endpoint (required)." )
6262 semiPersistDir = flag .String ("semi_persist_dir" , "/tmp" , "Local semi-persistent directory (optional)." )
63+
64+ workerMu sync.Mutex
65+ shuttingDown bool
6366)
6467
6568const (
@@ -307,19 +310,12 @@ func launchSDKProcess() error {
307310
308311 workerIds := append ([]string {* id }, info .GetSiblingWorkerIds ()... )
309312
310- // Keep track of child PIDs for clean shutdown without zombies
311- childPids := struct {
312- v []int
313- canceled bool
314- mu sync.Mutex
315- }{v : make ([]int , 0 , len (workerIds ))}
316-
317313 // Forward trapped signals to child process groups in order to terminate them gracefully and avoid zombies
318314 go func () {
319315 logger .Printf (ctx , "Received signal: %v" , <- signalChannel )
320- childPids . mu .Lock ()
321- childPids . canceled = true
322- for _ , pid := range childPids . v {
316+ workerMu .Lock ()
317+ shuttingDown = true
318+ for _ , pid := range activePids {
323319 go func (pid int ) {
324320 // This goroutine will be canceled if the main process exits before the 5 seconds
325321 // have elapsed, i.e., as soon as all subprocesses have returned from Wait().
@@ -330,7 +326,7 @@ func launchSDKProcess() error {
330326 }(pid )
331327 syscall .Kill (- pid , syscall .SIGTERM )
332328 }
333- childPids . mu .Unlock ()
329+ workerMu .Unlock ()
334330 }()
335331
336332 var wg sync.WaitGroup
@@ -342,9 +338,9 @@ func launchSDKProcess() error {
342338 bufLogger := tools .NewBufferedLogger (logger )
343339 errorCount := 0
344340 for {
345- childPids . mu .Lock ()
346- if childPids . canceled {
347- childPids . mu .Unlock ()
341+ workerMu .Lock ()
342+ if shuttingDown {
343+ workerMu .Unlock ()
348344 return
349345 }
350346
@@ -369,8 +365,8 @@ func launchSDKProcess() error {
369365
370366 logger .Printf (ctx , "Executing Python (%v): %v %v" , envStr , currentProg , strings .Join (currentArgs , " " ))
371367 cmd := StartCommandEnv (currentEnv , os .Stdin , bufLogger , bufLogger , currentProg , currentArgs ... )
372- childPids . v = append (childPids . v , cmd .Process .Pid )
373- childPids . mu .Unlock ()
368+ activePids = append (activePids , cmd .Process .Pid )
369+ workerMu .Unlock ()
374370
375371 var timer * time.Timer
376372 var profilingTimedOut atomic.Bool
@@ -379,8 +375,8 @@ func launchSDKProcess() error {
379375 if profilingActive && pcfg .StopAfterSec > 0 {
380376 duration := time .Duration (pcfg .StopAfterSec ) * time .Second
381377 timer = time .AfterFunc (duration , func () {
382- childPids . mu .Lock ()
383- defer childPids . mu .Unlock ()
378+ workerMu .Lock ()
379+ defer workerMu .Unlock ()
384380 if cmd .Process != nil {
385381 logger .Printf (ctx , "Profiling timeout of %d seconds reached. Sending SIGINT to worker %s" ,
386382 pcfg .StopAfterSec , workerId )
@@ -391,6 +387,7 @@ func launchSDKProcess() error {
391387 }
392388
393389 err := cmd .Wait ()
390+ unregisterPid (cmd .Process .Pid )
394391 if timer != nil {
395392 timer .Stop ()
396393 }
@@ -603,4 +600,22 @@ func logSubmissionEnvDependencies(ctx context.Context, bufLogger *tools.Buffered
603600 return nil
604601}
605602
603+ var (
604+ activePids []int
605+ )
606606
607+ func unregisterPid (pid int ) {
608+ workerMu .Lock ()
609+ defer workerMu .Unlock ()
610+ activePids = slices .DeleteFunc (activePids , func (p int ) bool {
611+ return p == pid
612+ })
613+ }
614+
615+ func getActivePids () []int {
616+ workerMu .Lock ()
617+ defer workerMu .Unlock ()
618+ pids := make ([]int , len (activePids ))
619+ copy (pids , activePids )
620+ return pids
621+ }
0 commit comments