github.com/billybanfield/evergreen@v0.0.0-20170525200750-eeee692790f7/plugin/builtin/shell/subtree_linux.go (about) 1 package shell 2 3 import ( 4 "bytes" 5 "fmt" 6 "io/ioutil" 7 "os" 8 9 "github.com/evergreen-ci/evergreen/plugin" 10 "github.com/mongodb/grip/slogger" 11 ) 12 13 func trackProcess(key string, pid int, log plugin.Logger) { 14 // trackProcess is a noop on linux, because we detect all the processes to be killed in 15 // cleanup() and we don't need to do any special bookkeeping up-front. 16 } 17 18 // getEnv returns a slice of environment variables for the given pid, in the form 19 // []string{"VAR1=FOO", "VAR2=BAR", ...} 20 // This function works by reading from /proc/$PID/environ, so the values returned only reflect 21 // the values of the environment variables at the time that the process was started. 22 func getEnv(pid int) ([]string, error) { 23 env, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/environ", pid)) 24 if err != nil { 25 // This is probably either "permission denied" because we do not own the process, 26 // or the process simply doesn't exist anymore. 27 return nil, err 28 } 29 parts := bytes.Split(env, []byte{0}) 30 results := make([]string, 0, len(parts)) 31 for _, part := range parts { 32 if len(part) == 0 { 33 continue 34 } 35 results = append(results, string(part)) 36 } 37 return results, nil 38 } 39 40 func cleanup(key string, log plugin.Logger) error { 41 pids, err := listProc() 42 if err != nil { 43 return err 44 } 45 pidMarker := fmt.Sprintf("EVR_AGENT_PID=%v", os.Getpid()) 46 taskMarker := fmt.Sprintf("EVR_TASK_ID=%v", key) 47 for _, pid := range pids { 48 env, err := getEnv(pid) 49 if err != nil { 50 continue 51 } 52 if envHasMarkers(env, pidMarker, taskMarker) { 53 p := os.Process{} 54 p.Pid = pid 55 if err := p.Kill(); err != nil { 56 log.LogTask(slogger.INFO, "Killing %v failed: %v", pid, err) 57 } else { 58 log.LogTask(slogger.INFO, "Killed process %v", pid) 59 } 60 } 61 } 62 return nil 63 }