@@ -66,13 +66,14 @@ type Tree struct {
66
66
stopped chan struct {}
67
67
68
68
// semaphore must be held when adding/deleting dynamic processes
69
- semaphore sync.Mutex
70
- strategy Strategy
71
- maxR int
72
- maxT time.Duration
73
- children map [string ]childProcess // map of children name to child process
74
- childrenOrder []string
75
- processChanged chan struct {} // indicates that some change to process slice has been made
69
+ semaphore sync.Mutex
70
+ strategy Strategy
71
+ maxR int
72
+ maxT time.Duration
73
+ children map [string ]childProcess // map of children name to child process
74
+ childrenOrder []string
75
+ childrenWaitGroup sync.WaitGroup
76
+ processChanged chan struct {} // indicates that some change to process slice has been made
76
77
77
78
logger Logger
78
79
@@ -251,6 +252,7 @@ func (t *Tree) Start(rootCtx context.Context) error {
251
252
if err := t .err (); err != nil {
252
253
return err
253
254
}
255
+ defer t .childrenWaitGroup .Wait ()
254
256
ctx , cancel := context .WithCancel (rootCtx )
255
257
defer cancel ()
256
258
t .gracefulCancel = cancel
@@ -348,7 +350,14 @@ func (t *Tree) handleTreeChanges(ctx context.Context, cancel context.CancelFunc)
348
350
349
351
func (t * Tree ) startChildProcess (ctx context.Context , processID int , p * ChildProcessSpecification , startSemaphore <- chan struct {}) {
350
352
childCtx , childWg , procState := t .plugStop (ctx , processID , p )
353
+ detachable := childCtx .Value (detachableContext ) == true
354
+ if ! detachable {
355
+ t .childrenWaitGroup .Add (1 )
356
+ }
351
357
go func () {
358
+ if ! detachable {
359
+ defer t .childrenWaitGroup .Done ()
360
+ }
352
361
defer childWg .Done ()
353
362
<- startSemaphore
354
363
t .logger .Println (p .Name , "child started" )
@@ -369,13 +378,16 @@ func (t *Tree) startChildProcess(ctx context.Context, processID int, p *ChildPro
369
378
type oversightValue string
370
379
371
380
func (t * Tree ) plugStop (ctx context.Context , processID int , p * ChildProcessSpecification ) (context.Context , * sync.WaitGroup , * state ) {
372
- childCtx , childCancel := context .WithCancel (context .WithValue (ctx , oversightValue ("name" ), p .Name ))
381
+ stopCtx , stopCancel := p .Shutdown ()
382
+ baseCtx := ctx
383
+ baseCtx = context .WithValue (baseCtx , oversightValue ("name" ), p .Name )
384
+ baseCtx = context .WithValue (baseCtx , detachableContext , stopCtx .Value (detachableContext ))
385
+ childCtx , childCancel := context .WithCancel (baseCtx )
373
386
var childWg sync.WaitGroup
374
387
childWg .Add (1 )
375
388
childProc := t .children [p .Name ]
376
389
childProc .state .setRunning (func () {
377
390
t .logger .Println (p .Name , "stopping" )
378
- stopCtx , stopCancel := p .Shutdown ()
379
391
defer stopCancel ()
380
392
wgComplete := make (chan struct {})
381
393
childCancel ()
0 commit comments