github.com/MetalBlockchain/metalgo@v1.11.9/vms/rpcchainvm/runtime/subprocess/linux_stopper.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 //go:build linux 5 // +build linux 6 7 // ^ SIGTERM signal is not available on Windows 8 // ^ syscall.SysProcAttr only has field Pdeathsig on Linux 9 10 package subprocess 11 12 import ( 13 "context" 14 "os/exec" 15 "syscall" 16 17 "go.uber.org/zap" 18 19 "github.com/MetalBlockchain/metalgo/utils/logging" 20 "github.com/MetalBlockchain/metalgo/utils/wrappers" 21 "github.com/MetalBlockchain/metalgo/vms/rpcchainvm/runtime" 22 ) 23 24 func NewCmd(path string, args ...string) *exec.Cmd { 25 cmd := exec.Command(path, args...) 26 cmd.SysProcAttr = &syscall.SysProcAttr{Pdeathsig: syscall.SIGTERM} 27 return cmd 28 } 29 30 func stop(ctx context.Context, log logging.Logger, cmd *exec.Cmd) { 31 waitChan := make(chan error) 32 go func() { 33 // attempt graceful shutdown 34 errs := wrappers.Errs{} 35 err := cmd.Process.Signal(syscall.SIGTERM) 36 errs.Add(err) 37 _, err = cmd.Process.Wait() 38 errs.Add(err) 39 waitChan <- errs.Err 40 close(waitChan) 41 }() 42 43 ctx, cancel := context.WithTimeout(ctx, runtime.DefaultGracefulTimeout) 44 defer cancel() 45 46 select { 47 case err := <-waitChan: 48 if err == nil { 49 log.Debug("subprocess gracefully shutdown") 50 } else { 51 log.Error("subprocess graceful shutdown failed", 52 zap.Error(err), 53 ) 54 } 55 case <-ctx.Done(): 56 // force kill 57 err := cmd.Process.Kill() 58 log.Error("subprocess was killed", 59 zap.Error(err), 60 ) 61 } 62 }