Code Monkey home page Code Monkey logo

Comments (11)

joepadmiraal avatar joepadmiraal commented on September 18, 2024 1

I had a look at what exec.Cmd has to offer and it seems they have something called StdinPipe which can be used to solve the problem. I've updated my demo repository with an example of how this could work.

Would it make sense to change the go-cmd implementation to start using StdinPipe?
Or maybe we can simply expose StdinPipe, StdoutPipe and StderrPipe?

from cmd.

daniel-nichter avatar daniel-nichter commented on September 18, 2024

Hi. Sorry, I don't understand the direction of programs. You said,

This allows the Go code to send instructions over stdin to the C program.

But in the sample code above, the C program is sending to the Go code?

from cmd.

joepadmiraal avatar joepadmiraal commented on September 18, 2024

Hi, thanks for responding.

Yes, the C program above is a minimal example to demonstrate the issue.
My actual program does read from stdin and write to stdout.

from cmd.

daniel-nichter avatar daniel-nichter commented on September 18, 2024

Does Go code also read on stdin? If so, then it's like echo hi | go | c (where c is being run by go)?

By the way, when I ran the example code above, nothing blocked, but I'm not sure if it's a functional example because // statusChan := testCmd.Start() suggests the Go isn't running the C.

from cmd.

joepadmiraal avatar joepadmiraal commented on September 18, 2024

The example does not read on stdin.
The commented out code was left over from a test I did.
The blocking happens with the row above statusChan := testCmd.StartWithStdin(rt)

I have created a small repository with a working example you can easily run:
https://github.com/joepadmiraal/cmd-test

from cmd.

hfrappier avatar hfrappier commented on September 18, 2024

@joepadmiraal, this is expected behaviour.

go-cmd uses exec.cmd.Wait internally, and https://golang.org/pkg/os/exec/#Cmd states that cmd.Wait, will not terminate until EOF or an error is read if you have a custom Stdin. Your TestReader always returns 0,nil, so this is expected behaviour.

Try this in your demo code, and it will no longer hang:

//Dummy reader which does nothing
type TestReader struct {
  start time.Time
}

//Read get's called by go-cmd
func (rt *TestReader) Read(p []byte) (n int, err error) {
   if time.Since(rt.start) > time.Second * 5 {
     err = io.EOF
   }
   return
}

from cmd.

joepadmiraal avatar joepadmiraal commented on September 18, 2024

Ok, but doesn't that make it impossible to detect whether a program has stopped?

If I want to stop the program from the Go code I can send the EOF via the reader.
But if the C program stops itself, it does not unblock.

from cmd.

MarcStdt avatar MarcStdt commented on September 18, 2024

Ok, but doesn't that make it impossible to detect whether a program has stopped?

If I want to stop the program from the Go code I can send the EOF via the reader.

But if the C program stops itself, it does not unblock.

I agree, I have to use a hacky workaround to detect if the program is still running (using gopsutil).
Would be nice to have a better solution there.

from cmd.

hfrappier avatar hfrappier commented on September 18, 2024

This is an edge case with io.Pipe usage within exec.Cmd iteslf, not go-cmd:

package main

import (
        "fmt"
        "time"
        "os/exec"
)

//Dummy reader which does nothing
type TestReader struct {
  after time.Time
}

var sent int
//Read get's called by go-cmd
func (rt *TestReader) Read(p []byte) (n int, err error) {
  if !rt.after.IsZero() && time.Now().After(rt.after) {
    n=1
  }
  return
}

type TestWriter struct {}
func (rt* TestWriter) Write(p []byte) (n int, err error) {
  fmt.Println(string(p))
  n = len(p)
  return
}

func main() {
        oscmd := exec.Command("c/seg", "")
        fail := &TestReader{}
        pass := &TestReader{time.Now().Add(time.Second *5)}
        _,_ = fail,pass
        tw := &TestWriter{}
        oscmd.Stdin = fail
        //oscmd.Stdin = pass
        oscmd.Stdout = tw
        oscmd.Start()
        oscmd.Wait()
        fmt.Println("Finished")
}

I'd expect a zero-length payload to detect whether a pipe was broken as well (e.g TCP)

from cmd.

YongBig avatar YongBig commented on September 18, 2024

我查看了 exec.Cmd 必须提供的内容,似乎他们有一个StdinPipe可以用来解决问题的东西。我已经更新了我的演示存储库,并提供了一个说明其工作原理的示例。

更改 go-cmd 实现以开始使用是否有意义StdinPipe? 或者也许我们可以简单地暴露StdinPipe, StdoutPipeand StderrPipe

I also encountered the same problem , are you have resolved the issue?
Looking forward to your sharing.

from cmd.

cr1cr1 avatar cr1cr1 commented on September 18, 2024

How about using io.Pipe with go-cmd?

	reader, writer := io.Pipe()
	go func() {
		_, _ = io.Copy(writer, bytes.NewBufferString("hello from the other side\n"))
		// close immediately
		_ = writer.Close()
	}()
	statusChan := testCmd.StartWithStdin(reader)
	...

Will not block, the buffer is sent to the child process stdin

from cmd.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.