Skip to content

Commit 28ad4ce

Browse files
author
Christian Weichel
committed
[supervisor] Make reaper terminating during shutdown
Fixes #2654
1 parent 193eb9b commit 28ad4ce

File tree

1 file changed

+27
-2
lines changed

1 file changed

+27
-2
lines changed

components/supervisor/pkg/supervisor/supervisor.go

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,15 @@ func Run(options ...RunOption) {
169169
}
170170
apiServices = append(apiServices, additionalServices...)
171171

172+
// The reaper can be turned into a terminating reaper by writing true to this channel.
173+
// When in terminating mode, the reaper will send SIGTERM to each child that gets reparented
174+
// to us and is still running. We use this mechanism to send SIGTERM to a shell child processes
175+
// that get reparented once their parent shell terminates during shutdown.
176+
terminatingReaper := make(chan bool, 1)
177+
172178
var wg sync.WaitGroup
173179
wg.Add(6)
174-
go reaper(ctx, &wg)
180+
go reaper(ctx, &wg, terminatingReaper)
175181
go startAndWatchIDE(ctx, cfg, &wg, ideReady)
176182
go startContentInit(ctx, cfg, &wg, cstate)
177183
go startAPIEndpoint(ctx, cfg, &wg, apiServices, apiEndpointOpts...)
@@ -203,6 +209,7 @@ func Run(options ...RunOption) {
203209
}
204210

205211
log.Info("received SIGTERM - tearing down")
212+
terminatingReaper <- true
206213
err = termMux.Close()
207214
if err != nil {
208215
log.WithError(err).Error("terminal closure failed")
@@ -305,16 +312,19 @@ func hasMetadataAccess() bool {
305312
return false
306313
}
307314

308-
func reaper(ctx context.Context, wg *sync.WaitGroup) {
315+
func reaper(ctx context.Context, wg *sync.WaitGroup, terminatingReaper <-chan bool) {
309316
defer wg.Done()
310317

318+
var terminating bool
311319
sigs := make(chan os.Signal, 128)
312320
signal.Notify(sigs, syscall.SIGCHLD)
313321
for {
314322
select {
315323
case <-ctx.Done():
316324
return
317325
case <-sigs:
326+
case terminating = <-terminatingReaper:
327+
continue
318328
}
319329

320330
pid, err := unix.Wait4(-1, nil, 0, nil)
@@ -325,6 +335,21 @@ func reaper(ctx context.Context, wg *sync.WaitGroup) {
325335
}
326336
if err != nil {
327337
log.WithField("pid", pid).WithError(err).Debug("cannot call waitpid() for re-parented child")
338+
continue
339+
}
340+
341+
if !terminating {
342+
continue
343+
}
344+
proc, err := os.FindProcess(pid)
345+
if err != nil {
346+
log.WithField("pid", pid).WithError(err).Debug("cannot find re-parented process")
347+
continue
348+
}
349+
err = proc.Signal(syscall.SIGTERM)
350+
if err != nil {
351+
log.WithField("pid", pid).WithError(err).Debug("cannot send SIGTERM to re-parented process")
352+
continue
328353
}
329354
}
330355
}

0 commit comments

Comments
 (0)