cmd/agent_wrapper/main_linux.go (35 lines of code) (raw):

// Copyright 2022 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //go:build !windows package main import ( "log" "os" "os/exec" "os/signal" "syscall" "time" ) const MaximumWaitForProcessStart = 5 * time.Second func handleSignals(cmd *exec.Cmd) { // Relay signals that should be passed down to the subprocess we are wrapping. sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT, syscall.SIGCONT) for { sig := <-sigs start := time.Now() // It is possible that we receive a signal before the code for `cmd.Run()` set cmd.Process. // In this case we wait up to MaximumWaitForProcessStart before giving up relaying the signal. for { if cmd.Process != nil { cmd.Process.Signal(sig) break } else if time.Until(start.Add(MaximumWaitForProcessStart)) <= 0 { // We waited MaximumWaitForProcessStart and the subprocess did not start. Give up on relaying the signal. log.Printf("Failed to relay signal %v to subprocess as it has not started yet", sig) break } time.Sleep(50 * time.Millisecond) } } } func runCommand(cmd *exec.Cmd) error { cmd.SysProcAttr = &syscall.SysProcAttr{ Pdeathsig: syscall.SIGKILL, } go handleSignals(cmd) return cmd.Run() }