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  }