Hi Michele,

Great to hear that!

I think we also need to painstakingly measure the action crash timeout to
avoid the delay for cold starts. Waiting for 100ms seems to be unduly.
Starting a new go routine is in the magnitude of microseconds, I’d expect
go runtime to fail the processes fast as well...

regards, Vadim.


On Sun, 11 Mar 2018 at 13:19 Michele Sciabarra <openwh...@sciabarra.com>
wrote:

> Hi Vadim, your suggestion worked.
>
> I was able to simplify the code a bit, but thanks to this I can remove the
> handshake while detecting immediately crashing executable. Fo the records,
> here is the code and the test:
>
> // startAndCheck
> func startAndCheck(cmd *exec.Cmd) error {
>         //fmt.Println(cmd.Path)
>         err := cmd.Start()
>         if err != nil {
>                 return err
>         }
>         ch := make(chan error)
>         go func() { ch <- cmd.Wait() }()
>         select {
>         case <-ch:
>                 return fmt.Errorf("command exited")
>         case <-time.After(100 * time.Millisecond):
>                 return nil
>         }
> }
>
> func Example_startAndCheck() {
>         // err
>         cmd := exec.Command("/does/not/exists")
>         cmd.StdinPipe()
>         cmd.StdoutPipe()
>         fmt.Println(startAndCheck(cmd))
>         // immediate exit
>         cmd = exec.Command("/bin/true")
>         cmd.StdinPipe()
>         cmd.StdoutPipe()
>         fmt.Println(startAndCheck(cmd))
>         // immediate exit with output
>         cmd = exec.Command("/bin/pwd")
>         cmd.StdinPipe()
>         cmd.StdoutPipe()
>         fmt.Println(startAndCheck(cmd))
>         // unwanted banner
>         cmd = exec.Command("/usr/bin/bc")
>         cmd.StdinPipe()
>         cmd.StderrPipe()
>         fmt.Println(startAndCheck(cmd))
>         // pipe loop
>         cmd = exec.Command("/bin/cat")
>         cmd.StdinPipe()
>         cmd.StderrPipe()
>         fmt.Println(startAndCheck(cmd))
>         // Output:
>         // fork/exec /does/not/exists: no such file or directory
>         // command exited
>         // command exited
>         // <nil>
>         // <nil>
> }
>
>
>
> --
>   Michele Sciabarra
>   openwh...@sciabarra.com
>
> On Sat, Mar 10, 2018, at 9:47 PM, Vadim Raskin wrote:
> > >> So, how can I check the process is actually terminated ?
> >
> > Hi Michele,
> >
> > what about using cmd.Wait() to check whether the process exited after you
> > started a go action? It will return a non-nil in case of error, otherwise
> > blocks forever waiting the process to finish. Waiting for a reasonable
> > amount of time to make sure that process doesn't exit and close the /init
> > call afterwards, would it cover the case you mentioned?
> >
> > Just to make sure we talk about the same thing:
> >
> > errorChan := chan string
> >
> > cmd := exec.Command("userBinary")
> > cmd.Start()
> > // wait for failure to happen
> > go func(){
> > err := cmd.Wait()
> > if(err != nil){
> > errorChan <- "exited with failure"
> > }
> > else {
> > close(errorChan)
> > }
> > }()
> > // wait at most 10ms for an error to happen
> > go func(){
> > time.Sleep(10 * time.Millisecond)
> > errorChan <- "happy"
> > }
> > runResult <- errorChan
> > // further processing.
> >
> > I haven't tested this code, it also needs to do some clean up of the Wait
> > go routine, but hopefully the logic is clear.
> >
> > regards,
> > Vadim.
> >
> > On Fri, Mar 9, 2018 at 3:18 PM Michele Sciabarra <mich...@sciabarra.com>
> > wrote:
> >
> > > > I would prefer it not be there, but can see the convenience of
> detecting
> > > > that an app has immediately crashed. If we can find another way to do
> > > > that via process inspection, that would be better in my view.
> > > >
> > > The problem can be summarised into this code:
> > >
> > >         // this command exits
> > >         cmd := exec.Command("true")
> > >         out, err := cmd.StdoutPipe()
> > >
> > >         err = cmd.Start()
> > >         fmt.Println(err)
> > >        // this is nil! no error!
> > >
> > >         // even worse! attempted to detect
> > >         err = cmd.Process.Signal(syscall.Signal(0))
> > >         // this is nil too! no error!
> > >         fmt.Println(err)
> > >
> > > So, how can I check the process is actually terminated ?
> > >
>

Reply via email to