func()

in agent/util/process/process.go [152:253]


func (p *ProcessCmd) SyncRun(
	workingDir string,
	commandName string,
	commandArguments []string,
	stdoutWriter io.Writer,
	stderrWriter io.Writer,
	stdinReader io.Reader,
	callbackFunc ReadCallbackFunc,
	timeOut int) (exitCode int, status int, err error) {

	status = Success
	exitCode = 0

	p.command = executil.Command(commandName, commandArguments...)
	p.command.Stdout = stdoutWriter
	p.command.Stderr = stderrWriter
	p.command.Stdin = stdinReader
	p.command.Dir = workingDir
	p.command.Env = p.env

	if err := p.prepareProcess(); err != nil {
		return 0, Fail, err
	}
	if p.user_name != "" {
		if err := p.addCredential(); err != nil {
			return 0, Fail, err
		}
	}

	if err = p.command.Start(); err != nil {
		log.GetLogger().Errorln("error occurred starting the command", err)
		exitCode = 1
		return exitCode, Fail, err
	}
	if p.collection != nil {
		if err := p.collection.AddProcess(p.command.Process); err != nil {
			log.GetLogger().WithError(err).Error("add process into collection failed")
			p.command.Process.Kill()
			return 1, Fail, fmt.Errorf("add process into collection failed: %v", err)
		} else {
			log.GetLogger().Infof("add process %d into collection %s success", p.command.Process.Pid, p.collection.Name())
		}
	}

	finished := make(chan WaitProcessResult, 1)
	go func() {
		processState, err := p.command.Process.Wait()
		finished <- WaitProcessResult{
			processState: processState,
			err:          err,
		}
	}()

	var timeoutChannel <-chan time.Time = nil
	if timeOut > 0 {
		timer := time.NewTimer(time.Duration(timeOut) * time.Second)
		defer timer.Stop()
		timeoutChannel = timer.C
	}
	select {
	case waitProcessResult := <-finished:
		log.GetLogger().Println("Command completed.", commandName)
		if waitProcessResult.processState != nil {
			if waitProcessResult.err != nil {
				log.GetLogger().WithFields(logrus.Fields{
					"processState": waitProcessResult.processState,
				}).WithError(waitProcessResult.err).Error("os.Process.Wait() returns error with valid process state")
			}

			exitCode = waitProcessResult.processState.ExitCode()
			// Sleep 200ms to allow remaining data to be copied back
			time.Sleep(time.Duration(200) * time.Millisecond)
			// Explicitly break select statement in case timer also times out
			break
		} else {
			exitCode = 1
			return exitCode, Fail, waitProcessResult.err
		}
	case <-timeoutChannel:
		log.GetLogger().Errorln("Timeout in run command.", commandName)
		exitCode = 1
		status = Timeout
		err = errors.New("timeout")
		if p.collection != nil {
			if err := p.collection.KillAll(); err != nil {
				log.GetLogger().WithError(err).Error("kill all process in collection failed")
			}
		} else {
			p.command.Process.Kill()
		}
	}

	if p.user_name != "" {
		p.removeCredential()
	}

	if p.collection != nil {
		p.collection.Dispose()
	}

	return exitCode, status, err
}