github.com/justinjmoses/evergreen@v0.0.0-20170530173719-1d50e381ff0d/plugin/builtin/shell/subtree_solaris.go (about)

     1  package shell
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"os/exec"
     7  	"regexp"
     8  	"strings"
     9  
    10  	"github.com/evergreen-ci/evergreen/plugin"
    11  	"github.com/mongodb/grip/slogger"
    12  )
    13  
    14  // This is a regex used to extract environment variables from the output of pargs -e
    15  // so that we can detect the 'tracer' strings.
    16  var pargsEnvPattern = regexp.MustCompile("^\\s*envp\\[\\d+\\]:\\s*(.*)$")
    17  
    18  func trackProcess(key string, pid int, log plugin.Logger) {
    19  	// trackProcess is a noop on solaris, because we detect all the processes to be killed in
    20  	// cleanup() and we don't need to do any special bookkeeping up-front.
    21  }
    22  
    23  // getEnv returns a slice of environment variables for the given pid, in the form
    24  // []string{"VAR1=FOO", "VAR2=BAR", ...}
    25  // This function works by calling "pargs -e $pid" and parsing its output.
    26  func getEnv(pid int) ([]string, error) {
    27  	/* In Solaris we extract environment variables by calling 'pargs -e $pid'
    28  	on each process in the system. The output of pargs looks like:
    29  	$ pargs -e 499
    30  	499:    /usr/perl5/bin/perl /usr/lib/intrd
    31  	envp[0]: PATH=/usr/sbin:/usr/bin
    32  	envp[1]: PWD=/
    33  	envp[2]: SHLVL=1
    34  	*/
    35  	out, err := exec.Command("pargs", "-e", fmt.Sprintf("%d", pid)).CombinedOutput()
    36  	if err != nil {
    37  		// Probably permission denied or process is gone away.
    38  		return nil, err
    39  	}
    40  	lines := strings.Split(string(out), "\n")
    41  	results := make([]string, 0, len(lines))
    42  	for _, line := range lines {
    43  		if matches := pargsEnvPattern.FindStringSubmatch(line); matches != nil {
    44  			results = append(results, matches[1])
    45  		}
    46  	}
    47  	return results, nil
    48  }
    49  
    50  func cleanup(key string, log plugin.Logger) error {
    51  	pids, err := listProc()
    52  	if err != nil {
    53  		return err
    54  	}
    55  	pidMarker := fmt.Sprintf("EVR_AGENT_PID=%v", os.Getpid())
    56  	taskMarker := fmt.Sprintf("EVR_TASK_ID=%v", key)
    57  	for _, pid := range pids {
    58  		env, err := getEnv(pid)
    59  		if err != nil {
    60  			continue
    61  		}
    62  		if envHasMarkers(env, pidMarker, taskMarker) {
    63  			p := os.Process{}
    64  			p.Pid = pid
    65  			if err := p.Kill(); err != nil {
    66  				log.LogSystem(slogger.INFO, "Cleanup killing %v failed: %v", pid, err)
    67  			} else {
    68  				log.LogTask(slogger.INFO, "Cleanup killed process %v", pid)
    69  			}
    70  		}
    71  	}
    72  	return nil
    73  }