Exemple #1
0
func (cmd *Cmd) Kill() error {
	switch cmd.State {
	case Running:
		cmd.State = Terminated
		lg.Debugf("Cmd:\tKilling %v\n", cmd.JobID)
		pgid, err := syscall.Getpgid(cmd.Cmd.Process.Pid)
		if err != nil {
			// Fall-back on error. Kill the main process only.
			cmd.Cmd.Process.Kill()
			break
		}
		// Kill the whole process group.
		syscall.Kill(-pgid, 15)

	case Finished:
		lg.Debug("Cmd:\tKilling pgroup %v\n", cmd.JobID)
		pgid, err := syscall.Getpgid(cmd.Cmd.Process.Pid)
		if err != nil {
			break
		}
		// Make sure to kill the whole process group,
		// so there are no subprocesses left.
		syscall.Kill(-pgid, 15)

	case Initialized:
		// This one is tricky, as the cmd's Start() might have
		// been called and is already in progress, but the cmd's
		// state is not Running yet.
		usCallingStartOnce := false
		cmd.StartOnce.Do(func() {
			cmd.WaitOnce.Do(func() {
				cmd.State = Invalidated
				cmd.StatusCode = -2
				cmd.Err = errors.New("invalidated")
				lg.Debugf("Cmd: Invalidating %v\n", cmd.JobID)
				close(cmd.Finished)
			})
			close(cmd.Started)
			usCallingStartOnce = true
		})
		if !usCallingStartOnce {
			// It was cmd.Start() that called StartOnce.Do(), not us,
			// thus we need to wait for Started and try to Kill again:
			<-cmd.Started
			cmd.Kill()
		}
	}

	return cmd.Err
}
func (p *execProcess) Start() error {
	if p.cmd.Stdout == nil {
		p.cmd.Stdout = p.stdoutWriter
	}

	if p.cmd.Stderr == nil {
		p.cmd.Stderr = p.stderrWriter
	}

	cmdString := strings.Join(p.cmd.Args, " ")
	p.logger.Debug(execProcessLogTag, "Running command '%s'", cmdString)

	if !p.keepAttached {
		p.cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	}

	err := p.cmd.Start()
	if err != nil {
		return bosherr.WrapErrorf(err, "Starting command '%s'", cmdString)
	}

	if !p.keepAttached {
		p.pgid = p.cmd.Process.Pid
	} else {
		p.pgid, err = syscall.Getpgid(p.pid)
		if err != nil {
			p.logger.Error(execProcessLogTag, "Failed to retrieve pgid for command '%s'", cmdString)
			p.pgid = -1
		}
	}

	return nil
}
Exemple #3
0
Fichier : qst.go Projet : heyLu/qst
func (r *Runner) Kill() error {
	pgid, err := syscall.Getpgid(r.cmd.Process.Pid)
	if err == nil {
		syscall.Kill(-pgid, syscall.SIGTERM)
	}
	return err
}
Exemple #4
0
func (k *PosixKernel) Getpgid(pid int) uint64 {
	n, err := syscall.Getpgid(pid)
	if err != nil {
		return Errno(err)
	}
	return uint64(n)
}
//KillGroupProcess ...
func killGroupProcess(cmd *exec.Cmd) {
	pgid, err := syscall.Getpgid(cmd.Process.Pid)
	if err == nil {
		err = syscall.Kill(-pgid, 15)
		printError("syscall Kill :", err)
		sendMessage("info", "Run aborted\n")
	}
}
Exemple #6
0
// Satisfies the Listener interface and calls the relevant binary file
func (this *Cli) Exec(evt event.Event) {

	this.Log.Handler(this, &evt)

	bin := magicString(this.Config.GetBin(), evt)
	stdin := magicString(this.Config.GetStdin(), evt)
	args := append([]string(nil), this.Config.GetArgs()...)
	for i, arg := range this.Config.GetArgs() {
		args[i] = magicString(arg, evt)
	}

	cmd := exec.Command(bin, args...)
	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	cmd.Stdin = strings.NewReader(stdin)
	var out bytes.Buffer
	var sErr bytes.Buffer
	cmd.Stdout = &out
	cmd.Stderr = &sErr

	this.Log.Info("CLI CMD %s %s \"%s %s\"", evt.GetId(), this.GetName(), bin, strings.Join(args, " "))
	err := cmd.Start()
	if err != nil {
		this.Log.Error("CLI ERR %s %s \"%s\"", evt.GetId(), this.GetName(), sErr.String())
		this.Log.HandlerError(this, err.Error(), &evt)
		return
	}

	timeOut := this.Config.GetTimeout()
	if timeOut == 0 {
		if err := cmd.Wait(); err != nil {
			this.Log.Error("CLI ERROR %s", err.Error())
		}
	} else {
		// this allows us to set a timeout on the cli (phantomjs def needs this)
		done := make(chan error, 1)
		go func() {
			done <- cmd.Wait()
		}()
		select {
		case <-time.After(time.Duration(timeOut) * time.Second):
			pgid, err := syscall.Getpgid(cmd.Process.Pid)
			if err == nil {
				syscall.Kill(-pgid, 15) // note the minus sign
				this.Log.Warning("CLITIMEOUT %s %s", evt.GetId(), this.GetName())
			}
			<-done // allow goroutine to exit
		case err := <-done:
			if err != nil {
				this.Log.Error("CLI ERROR %s", err.Error())
			}
		}

	}

	this.Log.Debug("CLI OUT %s %s \"%s\"", evt.GetId(), this.GetName(), out.String())
}
Exemple #7
0
func (c *command) Info() (pid, pgrp int) {
	pid = c.proc.Process.Pid

	pgrp, err := syscall.Getpgid(pid)
	if err != nil {
		c.test.Fatal(err)
	}

	return
}
Exemple #8
0
func killall(multierr io.Writer, cmd *exec.Cmd) {
	cmd.Start()

	pgid, err := syscall.Getpgid(cmd.Process.Pid)
	if err == nil {
		syscall.Kill(-pgid, 15) // note the minus sign
		cmd.Wait()
	} else {
		fmt.Fprintf(multierr, "\n%v\n", err)
	}
}
Exemple #9
0
func sendSignalToProcess(process *os.Process, what values.Signal, tryGroup bool) error {
	if tryGroup {
		pgid, err := syscall.Getpgid(process.Pid)
		if err == nil {
			if syscall.Kill(-pgid, syscall.Signal(what)) == nil {
				return nil
			}
		}
	}
	process.Signal(syscall.Signal(what))
	return nil
}
Exemple #10
0
// Kill a script run and all child processes
func (self *ScriptRun) kill() error {
	if self.Cmd == nil {
		return errors.New("Cmd is nil")
	} else if self.Cmd.Process == nil {
		return errors.New("Cmd.Process is nil")
	}
	pgid, err := syscall.Getpgid(self.Cmd.Process.Pid)
	if err != nil {
		return err
	}
	return syscall.Kill(-pgid, syscall.SIGKILL)
}
Exemple #11
0
// kills a cmd process based on config timeout settings
func killProcessOnTimeout(cmd *exec.Cmd, timeout time.Duration) (exitCode int, err error) {
	// 1 deep channel for done
	done := make(chan error, 1)

	go func() {
		done <- cmd.Wait()
	}()

	processGroupID, err := syscall.Getpgid(cmd.Process.Pid)
	if err != nil {
		return 0, err
	}

	grimProcessGroupID, err := syscall.Getpgid(os.Getpid())
	if err != nil {
		return 0, err
	}

	select {
	case <-time.After(timeout):
		exitCode = -23
		err = errTimeout
	case err := <-done:
		if err != nil {
			exitCode, err = getExitCode(err)
			if err != nil {
				return 0, fmt.Errorf("Build Error: %v", err)
			}
		}
	}

	if grimProcessGroupID != processGroupID {
		syscall.Kill(-processGroupID, syscall.SIGKILL)
	}

	return
}
Exemple #12
0
func TestIPERF(t *testing.T) {

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		if <-c != syscall.SIGTERM {
			panic(nil)
		}
	}()

	if len(os.Getenv("IPERF")) != 0 {
		cmd0 := exec.Command("iperf3", "-s", "", "-p", "5203")
		cmd0.Start()
		pid := cmd0.Process.Pid
		go cmd0.Wait()

		t0 := Accelerate("tcp://:41501-41504,udp://:42401-42404", "tcp://127.0.0.1:5203", BACKEND)
		t0.WaitforAlive()
		t1 := Accelerate("tcp://:50500", "tcp://127.0.0.1:41501-41504,udp://127.0.0.1:42401-42404", FRONTEND)
		t1.WaitforAlive()

		//iperfExec(exec.Command("iperf3", "-c", "127.0.0.1", "-p", "50500", "-R", "-P", "3"))
		//iperfExec(exec.Command("iperf3", "-c", "127.0.0.1", "-p", "50500", "-b", "10M"))
		cmd1 := exec.Command("iperf3", "-c", "127.0.0.1", "-p", "50500", "--get-server-output")
		iperfExec(cmd1)
		if len(os.Getenv("CPU")) != 0 {
			f, err := os.Create("cpu.profile")
			if err != nil {
				log.Fatal(err)
			}
			pprof.StartCPUProfile(f)
			defer pprof.StopCPUProfile()
		}
		cmd1.Wait()

		cmd2 := exec.Command("iperf3", "-c", "127.0.0.1", "-p", "50500", "-R", "--get-server-output")
		iperfExec(cmd2)
		cmd2.Wait()

		t0.Status()
		t1.Status()

		pgid, err := syscall.Getpgid(pid)
		if err == nil {
			syscall.Kill(-pgid, 15) // note the minus sign
		}
	}
}
Exemple #13
0
func killall(multierr io.Writer, cmd *exec.Cmd) {
	pgid, err := syscall.Getpgid(cmd.Process.Pid)

	// don't kill myself if cmd is running in same process group
	if pgid == os.Getpid() || pgid == os.Getgid() {
		cmd.Process.Kill()
		return
	}

	if err == nil {
		syscall.Kill(-pgid, 15) // note the minus sign
		cmd.Wait()
	} else {
		fmt.Fprintf(multierr, "\n%v\n", err)
	}
}
func (x *ProcessManager) KillProcesses() error {
	x.processes.Lock()
	defer x.processes.Unlock()
	for _, pi := range x.processes.values {
		// we could potentially fail before the processes are correctly started
		// in that case, do nothing
		if pi.cmd.Process != nil {
			pgid, err := syscall.Getpgid(pi.cmd.Process.Pid)
			if err != nil {
				return err
			}
			syscall.Kill(-pgid, 15)
		}
	}
	return nil
}
Exemple #15
0
func (i *instance) cmdKill(req *Request) (*Response, error) {
	glog.Infoln("Server going down with SIGKILL")
	glog.Flush()

	pgid, err := syscall.Getpgid(0)
	if err != nil {
		glog.Errorln("Failed to get pgid", err)
		os.Exit(1)
	}

	err = syscall.Kill(-pgid, syscall.SIGKILL)
	if err != nil {
		glog.Errorln("Failed to kill our process group", err)
		os.Exit(1)
	}

	// We'll never get here...
	return nil, nil
}
Exemple #16
0
func fg(ec *EvalCtx, pids ...int) {
	if len(pids) == 0 {
		throw(ErrArgs)
	}
	var thepgid int
	for i, pid := range pids {
		pgid, err := syscall.Getpgid(pid)
		maybeThrow(err)
		if i == 0 {
			thepgid = pgid
		} else if pgid != thepgid {
			throw(ErrNotInSameGroup)
		}
	}

	err := sys.Tcsetpgrp(0, thepgid)
	maybeThrow(err)

	errors := make([]Error, len(pids))

	for i, pid := range pids {
		err := syscall.Kill(pid, syscall.SIGCONT)
		if err != nil {
			errors[i] = Error{err}
		}
	}

	for i, pid := range pids {
		if errors[i] != OK {
			continue
		}
		var ws syscall.WaitStatus
		_, err = syscall.Wait4(pid, &ws, syscall.WUNTRACED, nil)
		if err != nil {
			errors[i] = Error{err}
		} else {
			// TODO find command name
			errors[i] = Error{NewExternalCmdExit(fmt.Sprintf("(pid %d)", pid), ws, pid)}
		}
	}

	throwCompositeError(errors)
}
Exemple #17
0
// isLeader determines, whether g is still the leader of the process group
func (g *Group) isLeader() (ok bool, err error) {
	if g == nil {
		return false, syscall.ESRCH
	}
	pgid, err := syscall.Getpgid(g.pid)
	if err != nil {
		return false, err
	}

	// Pids 0 and 1 will have special meaning, so don't return them.
	if pgid < 2 {
		return false, nil
	}

	// the process is not the leader?
	if pgid != g.pid {
		return false, nil
	}
	return true, nil
}
Exemple #18
0
// This should only be called from within the Runnable
// which ensures that the process has started and so can be killed
func (cmd *Cmd) Kill(proc chan error) {
	log.Info("Sending signal SIGTERM to command:", cmd.Name)

	pgid, err := syscall.Getpgid(cmd.Process.Pid)
	if err != nil {
		if err.Error() == "no such process" {
			log.Info("Process exited before SIGTERM:", cmd.Name)
		} else {
			log.Err("Error getting process group:", err)
		}
		return
	}

	if err := syscall.Kill(-pgid, syscall.SIGTERM); err != nil {
		log.Warn("Failed to send SIGTERM, command must have exited (name, error):", cmd.Name, err)
		return
	}

	// give process time to exit…
	timerDone := make(chan struct{})
	timer := time.AfterFunc(time.Duration(*exitWait)*time.Millisecond, func() {
		close(timerDone)
	})

	select {
	case <-timerDone:
	case <-proc:
		timer.Stop()
		return
	}

	log.Info("After exitwait, command still running, sending SIGKILL…")
	if err := syscall.Kill(-pgid, syscall.SIGKILL); err != nil {
		if err.Error() == "no such process" {
			log.Info("Process exited before SIGKILL:", cmd.Name)
		} else {
			log.Err("Error killing command (cmd, error):", cmd.Name, err)
		}
	}
}
Exemple #19
0
func (sc *ServiceConfig) stopProcess(cfg OperationConfig, command *ServiceCommand, graceful bool) (success bool, err error) {
	pgid, err := syscall.Getpgid(command.Pid)
	if err != nil {
		return false, errors.WithStack(err)
	}

	if pgid == 0 || pgid == 1 {
		return false, errors.WithStack(errors.New("suspect pgid: " + strconv.Itoa(pgid)))
	}

	err = command.killGroup(cfg, pgid, graceful)
	if err != nil {
		return false, errors.WithStack(err)
	}

	// Check to see if the process is still running
	exists, err := process.PidExists(int32(command.Pid))
	if err != nil {
		return false, errors.WithStack(err)
	}

	return !exists, nil
}
Exemple #20
0
func terminateProc(proc string) error {
	p := procs[proc].cmd.Process
	if p == nil {
		return nil
	}

	pgid, err := syscall.Getpgid(p.Pid)
	if err != nil {
		return err
	}

	// use pgid, ref: http://unix.stackexchange.com/questions/14815/process-descendants
	pid := p.Pid
	if pgid == p.Pid {
		pid = -1 * pid
	}

	target, err := os.FindProcess(pid)
	if err != nil {
		err = target.Signal(syscall.SIGHUP)
	}
	return err
}
func (r *ConcreteCmdRunner) Run(command string, args ...string) error {
	cmd := exec.Command(command, args...)
	cmd.Stdout = r.Stdout
	cmd.Stderr = r.Stderr
	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	if err := cmd.Start(); err != nil {
		return err
	}

	timer := time.AfterFunc(r.Timeout, func() {
		pgid, err := syscall.Getpgid(cmd.Process.Pid)
		if err == nil {
			syscall.Kill(-pgid, 15)
		}
	})

	err := cmd.Wait()

	if !timer.Stop() {
		return &TimeoutError{}
	}

	return err
}
Exemple #22
0
// ProcessGroup determines the process group of p and if we are their leader
func ProcessGroup(p *os.Process) (grp *os.Process, err error) {
	if p == nil {
		return nil, syscall.ESRCH
	}
	pgid, err := syscall.Getpgid(p.Pid)
	if err != nil {
		return nil, err
	}

	// Pids 0 and 1 will have special meaning, so don't return them.
	if pgid < 2 {
		return nil, ErrNotLeader
	}

	// the process is not the leader?
	if pgid != p.Pid {
		return nil, ErrNotLeader
	}

	// This just creates a process object from a Pid in Unix
	// instead of actually searching it.
	grp, err = os.FindProcess(-pgid)
	return grp, err
}
Exemple #23
0
// NewControlledProcess creates the child proc.
func NewControlledProcess(cmd string, arguments []string, doneChan chan error, stdoutLimit int64) (JobControl, error) {
	var err error

	j := &Job{
		nil,
		nil,
		0,
		0,
		doneChan,
		stdoutLimit,
		nil,
	}

	// Drop command from cmdline arguments and pass the rest as arguments separately
	var args []string
	if len(arguments) > 0 {
		args = arguments[1:]
	}
	j.Cmd = exec.Command(cmd, args...)

	// Collect stdout from the process to redirect to real stdout
	stdoutpipe, err := j.Cmd.StdoutPipe()
	if err != nil {
		return nil, fmt.Errorf("Failed to acquire stdout: %s", err)
	}
	stdout := iocontrol.NewMeasuredReader(stdoutpipe)
	j.stdoutReader = stdout

	var wg sync.WaitGroup

	stdin, err := j.Cmd.StdinPipe()
	if err != nil {
		return nil, fmt.Errorf("Failed to acquire stdin: %s", err)
	}

	stderr, err := j.Cmd.StderrPipe()
	if err != nil {
		return nil, fmt.Errorf("Failed to acquire stderr: %s", err)
	}

	// Map all child processes under this tree so Kill really ends everything.
	j.Cmd.SysProcAttr = &syscall.SysProcAttr{
		Setpgid: true, // Set process group ID
	}

	log.Debugf("%#v\n", j.Cmd)

	// Start the sub-process but don't wait for completion to pickup the Pid
	// for resource monitoring.
	err = j.Cmd.Start()
	if err != nil {
		return nil, fmt.Errorf("Failed to execute sub-process: %s\n", err)
	}

	j.Pid = j.Cmd.Process.Pid
	j.Pgid, err = syscall.Getpgid(j.Pid)
	if err != nil {
		return nil, fmt.Errorf("Failed syscall.Getpgid: %s\n", err)
	}

	j.Proc, err = process.NewProcess(int32(j.Pgid))
	if err != nil {
		return nil, fmt.Errorf("Unable to create process.NewProcess: %s\n", err)
	}

	wg.Add(1)
	go func(wg *sync.WaitGroup, r io.Reader) {
		defer wg.Done()
		io.Copy(os.Stdout, r)
		log.Debugln("child closed stdout")
	}(&wg, stdout)

	go func(w io.WriteCloser) {
		io.Copy(w, os.Stdin)
	}(stdin)

	wg.Add(1)
	go func(wg *sync.WaitGroup, r io.Reader) {
		defer wg.Done()
		io.Copy(os.Stderr, r)
		log.Debugln("child closed stderr")
	}(&wg, stderr)

	// Background waiting for the job to finish and emit a done channel message
	// when complete.
	go func(wg *sync.WaitGroup, j *Job) {
		log.Debugln("Waiting on wg.Wait()")
		wg.Wait()
		log.Debugln("Waiting on Cmd.Wait()")
		err := j.Cmd.Wait()
		log.Debugf("Job finished: %q\n", err)
		j.done <- err
	}(&wg, j)

	return j, nil
}
Exemple #24
0
/*
	Execute a command (using arguments 'args')
	Redirect stdout to outFile    (unless file name is empty)
	Redirect stderr to errFile    (unless file name is empty)
	Write exit code to exitFile   (unless file name is empty)
	Timeout after timeout seconds (unless time is zero)
*/
func (be *BdsExec) executeCommand() int {
	if DEBUG {
		log.Printf("Debug, executeCommand %s\n", be.command)
	}

	// Redirect all signals to channel (e.g. Ctrl-C)
	osSignal := make(chan os.Signal)

	if be.taskLoggerFile != "" {
		// Main bds program
		signal.Notify(osSignal) // Capture all signals
	} else {
		// Set a new process group.
		// We want to be able to kill all child processes, without killing the
		// calling program. E.g. When running using a local executor, the Java Bds
		// calls 'bds exec', so sending a kill to the group when a timeOut occurs,
		// would also kill the parent Java program and kill the whole bds execution
		// (clearly not what we want).
		// To avoid this, we create a new group thus we can send a kill signal to
		// this new process group.

		gpidOri, _ := syscall.Getpgid(0)
		if err := syscall.Setpgid(0, 0); err != nil {
			// During an ssh remote execution we will no be albe to do this.
			// In this case, we assume that the SSH daemon will catch the sinals
			// and kill al child processes.
			if DEBUG {
				log.Printf("Error setting process group: %s", err)
			}
		}

		if DEBUG {
			gpidNew, _ := syscall.Getpgid(0)
			log.Printf("Info: Setting new process group. Original GPID: %d, new GPID: %d\n", gpidOri, gpidNew)
		}
	}

	// Create command
	be.cmd = exec.Command(be.command)
	be.cmd.Args = be.cmdargs

	// Copy stdout
	stdout := tee.NewTee(be.outFile, false)
	defer stdout.Close()
	be.cmd.Stdout = stdout

	// Copy stderr
	stderr := tee.NewTee(be.errFile, true)
	defer stderr.Close()
	be.cmd.Stderr = stderr

	// Connect to stdin
	be.cmd.Stdin = os.Stdin

	// Start process
	err := be.cmd.Start()
	if err != nil {
		log.Fatal(err)
	}

	be.exitCode = be.executeCommandTimeout(osSignal)
	if DEBUG {
		log.Printf("Debug, executeCommand: Exit code %d\n", be.exitCode)
	}
	return be.exitCode
}
Exemple #25
0
func (cr *ConsoleRunner) handleConsoleRunnerRun(b core.Bot, m *slack.Message) error {
	messageWithoutMentions := util.TrimWhitespace(core.LessSpecificMention(m.Text, b.ID()))
	cleanedMessage := core.FixLinks(messageWithoutMentions)

	pieces := strings.Split(cleanedMessage, " ")
	if len(pieces) < 2 {
		return exception.Newf("invalid arguments for `%s`", ActionConsoleRunnerRun)
	}

	commandWithArguments := pieces[1:]
	command := commandWithArguments[0]
	args := []string{}
	if len(commandWithArguments) > 1 {
		args = commandWithArguments[1:]
	}

	if !cr.isWhitelistedCommand(command) {
		return exception.Newf("`%s` cannot run %s", ActionConsoleRunnerRun, command)
	}

	cmdFullPath, lookErr := exec.LookPath(command)
	if lookErr != nil {
		return exception.Wrap(lookErr)
	}

	stdoutBuffer := bytes.NewBuffer([]byte{})
	subCmd := exec.Command(cmdFullPath, args...)
	subCmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	subCmd.StdoutPipe()
	subCmd.StderrPipe()
	subCmd.Stdout = stdoutBuffer
	subCmd.Stderr = stdoutBuffer

	startErr := subCmd.Start()
	if startErr != nil {
		return startErr
	}

	started := time.Now().UTC()

	didTimeout := false
	go func() {
		for {
			now := time.Now().UTC()
			if now.Sub(started) > ConsoleRunnerTimeout {
				didTimeout = true
				pgid, err := syscall.Getpgid(subCmd.Process.Pid)
				if err != nil {
					return
				}
				syscall.Kill(-pgid, 15)
			}
			time.Sleep(50 * time.Millisecond)
		}
	}()

	subCmd.Wait()

	timedOutText := ""
	if didTimeout {
		timedOutText = " (timed out)"
	}

	stdout := stdoutBuffer.String()
	outputText := fmt.Sprintf("console runner stdout%s:\n", timedOutText)
	if len(stdout) != 0 {
		prefixed := strings.Replace(stdout, "\n", "\n>", -1)
		outputText = outputText + fmt.Sprintf(">%s", prefixed)
	} else {
		outputText = "> empty"
	}

	return b.Say(m.Channel, outputText)
}
Exemple #26
0
//Execute a command by specifying executable and arguments, returns statuscode and output summary
func Execute(timeout int, cmdName string, cmdArgs ...string) (status int, output string) {
	// TODO: Check if cmdName file exists
	cmd := exec.Command(cmdName, cmdArgs...)

	cmdOutput := &bytes.Buffer{}
	errOutput := &bytes.Buffer{}

	fail := false
	killed := false

	cmd.Stdout = cmdOutput
	cmd.Stderr = errOutput

	var waitStatus syscall.WaitStatus

	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
	cmd.Start()

	timer := time.AfterFunc(time.Duration(timeout+1)*time.Second, func() {
		if cmd.Process != nil {
			pgid, err := syscall.Getpgid(cmd.Process.Pid)
			if err == nil {
				syscall.Kill(-pgid, 9) // note the minus sign
				log.Notice("Killed PID", pgid, "because of timeout of ", timeout, "seconds while running", cmdName)
				killed = true
			}
		} else {
			log.Error("Tried to kill but it didn't exist (anymore).", cmdName, cmdArgs)
		}
	})

	if err := cmd.Wait(); err != nil {
		if err != nil {
			fail = true
		}
		if exitError, ok := err.(*exec.ExitError); ok {
			waitStatus = exitError.Sys().(syscall.WaitStatus)
		}
	} else {
		// Success
		waitStatus = cmd.ProcessState.Sys().(syscall.WaitStatus)
	}

	if killed {
		return killedStatus()
	}

	timer.Stop()

	outputString := string(cmdOutput.Bytes())
	shortOutputStrings := strings.Split(outputString, "\n")
	statusCode := waitStatus.ExitStatus()

	if waitStatus.ExitStatus() == -1 {
		return killedStatus()
	}

	if waitStatus.ExitStatus() == 0 && fail {
		statusCode = 420
	}

	return statusCode, shortOutputStrings[0]
}
Exemple #27
0
func (su *Supervise) KillProc() {
	var pgid, err = syscall.Getpgid(su.pid)
	if err == nil {
		syscall.Kill(-pgid, syscall.SIGKILL)
	}
}
Exemple #28
0
func getPgID(cmd *exec.Cmd) (int, error) {
	return syscall.Getpgid(cmd.Process.Pid)
}
Exemple #29
0
// Run command, maar onderbreek het als chKill of chGlobalExit gesloten is
func run(cmd *exec.Cmd, chKill chan bool, chPipe chan string) error {
	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}

	chRet := make(chan error, 2)
	// deze functie schrijft twee keer op chRet
	go func() {
		if chPipe == nil {
			cmd.Start()
			chRet <- nil
			err := cmd.Wait()
			chRet <- err
			return
		}

		pipe, err := cmd.StdoutPipe()
		if err != nil {
			chRet <- nil
			chRet <- err
			return
		}
		cmd.Start()
		chRet <- nil

		var err1, err2 error

		rd := util.NewReader(pipe)
		for {
			var line string
			line, err1 = rd.ReadLineString()
			if err1 == io.EOF {
				err1 = nil
				break
			}
			if err1 != nil {
				break
			}
			chPipe <- line
		}
		close(chPipe)

		err2 = cmd.Wait()

		if err1 != nil {
			chRet <- err1
		} else {
			chRet <- err2
		}
	}()

	<-chRet // commando is gestart

	pgid, err := syscall.Getpgid(cmd.Process.Pid)
	if err != nil {
		// misschien betekent een fout alleen maar dat het process net klaar is
		logf("BIG TROUBLE: syscall.Getpgid(cmd.Process.Pid) error: %v", err)
		pgid = 0
	}

FORSELECT:
	for {
		select {
		case err = <-chRet:
			return err
		case <-chGlobalExit:
			break FORSELECT
		case <-chKill:
			break FORSELECT
		}
	}
	for _, sig := range []int{15, 9} {
		err = syscall.Kill(-pgid, syscall.Signal(sig))
		if err != nil {
			logf("syscall.Kill(-pgid, %d) error: %v", sig, err)
		}
		if sig != 9 {
			time.Sleep(2 * time.Second)
		}
	}
	err = <-chRet
	return err
}
Exemple #30
0
// KillProcess kills the new process created by StartNewProcess
// It kills the whole process group to ensure
// all of its child processes are killed
func (w *watch) KillProcess() {
	pgid, err := syscall.Getpgid(w.cmd.Process.Pid)
	if err == nil {
		syscall.Kill(-pgid, syscall.SIGTERM)
	}
}