in openwhisk/executor.go [128:187]
func (proc *Executor) Start(waitForAck bool) error {
// start the underlying executable
Debug("Start:")
err := proc.cmd.Start()
if err != nil {
Debug("run: early exit: %e", err)
proc.cmd = nil // no need to kill
return fmt.Errorf("command exited")
}
Debug("pid: %d", proc.cmd.Process.Pid)
go func() {
proc.cmd.Wait()
proc.exited <- true
}()
// not waiting for an ack, so use a timeout
if !waitForAck {
select {
case <-proc.exited:
return fmt.Errorf("command exited")
case <-time.After(DefaultTimeoutStart):
return nil
}
}
// wait for acknowledgement
Debug("waiting for an ack")
ack := make(chan error)
go func() {
out, err := proc.output.ReadBytes('\n')
Debug("received ack %s", out)
if err != nil {
ack <- err
return
}
// parse ack
var ackData ActionAck
err = json.Unmarshal(out, &ackData)
if err != nil {
ack <- err
return
}
// check ack
if !ackData.Ok {
ack <- fmt.Errorf("The action did not initialize properly.")
return
}
ack <- nil
}()
// wait for ack or unexpected termination
select {
// ack received
case err = <-ack:
return err
// process exited
case <-proc.exited:
return fmt.Errorf("Command exited abruptly during initialization.")
}
}