FAQ
// begin code
package main

import "fmt"
import "os/exec"
import "log"
import "runtime"

var done = make(chan error)

func watch() {
for {
select {
case err := <-done:
log.Printf("process done with error = %v", err)
}
}
}

func main() {
go watch()
var err error
fmt.Println("Hello, playground")
app1 := exec.Command("arecord")
app2 := exec.Command("aplay")
if app2.Stdin, err = app1.StdoutPipe(); err != nil {
log.Fatal(err)
}
if err := app1.Start(); err != nil {
log.Fatal(err)
}
if err = app2.Start(); err != nil {
log.Fatal(err)
}
go func() {
done <- app1.Wait()
}()
go func() {
done <- app2.Wait()
}()

for{runtime.Gosched()}
}
//end code

When you execute in a shell `arecord|aplay`, you can killall aplay and
arecord will exit OR you can killall arecord and aplay will exit.
I try to do the same thing in this example.
If I killall arecord, aplay will exit. Good
If I killall aplay, arecord stays there, and aplay exits. Not good.
Any idea ?
Thanks !

--

Search Discussions

  • Skip Tavakkolian at Oct 10, 2012 at 6:20 pm
    close app2.Stdin after sub processes have started.

    in the first instance the reader gets an error because the writer has
    gone away and closed the write end and the reader exits. in the second
    case the writer doesn't get an error when a reader (aplay) has gone
    away because your main proc still has a duplicate of the file; the
    writer blocks when the pipe buffer is full.

    http://play.golang.org/p/Lps1zNplPp
    On Wed, Oct 10, 2012 at 9:41 AM, GGGo wrote:
    // begin code
    package main

    import "fmt"
    import "os/exec"
    import "log"
    import "runtime"

    var done = make(chan error)

    func watch() {
    for {
    select {
    case err := <-done:
    log.Printf("process done with error = %v", err)
    }
    }
    }

    func main() {
    go watch()
    var err error
    fmt.Println("Hello, playground")
    app1 := exec.Command("arecord")
    app2 := exec.Command("aplay")
    if app2.Stdin, err = app1.StdoutPipe(); err != nil {
    log.Fatal(err)
    }
    if err := app1.Start(); err != nil {
    log.Fatal(err)
    }
    if err = app2.Start(); err != nil {
    log.Fatal(err)
    }
    go func() {
    done <- app1.Wait()
    }()
    go func() {
    done <- app2.Wait()
    }()

    for{runtime.Gosched()}
    }
    //end code

    When you execute in a shell `arecord|aplay`, you can killall aplay and
    arecord will exit OR you can killall arecord and aplay will exit.
    I try to do the same thing in this example.
    If I killall arecord, aplay will exit. Good
    If I killall aplay, arecord stays there, and aplay exits. Not good.
    Any idea ?
    Thanks !

    --
    --
  • GGGo at Oct 10, 2012 at 9:34 pm
    I don't understand why the main func keep a duplicate of the file, but what
    you did solve my problem for sure. Thank you.

    I also notice something, if I run ./main in the shell, and type Ctrl+C, the
    main program exits and app1 and app2 exit too. Great. But If I killall
    main, app1 and app2 still running. (killall main or kill -9 PID or kill -2
    PID)

    So it means if the main program crashes, app1 and app2 will continue to
    run. Right ? Is there something I can do to attach child commands to the
    main to prevent this ?
    On Wednesday, October 10, 2012 2:12:29 PM UTC-4, Skip wrote:

    close app2.Stdin after sub processes have started.

    in the first instance the reader gets an error because the writer has
    gone away and closed the write end and the reader exits. in the second
    case the writer doesn't get an error when a reader (aplay) has gone
    away because your main proc still has a duplicate of the file; the
    writer blocks when the pipe buffer is full.

    http://play.golang.org/p/Lps1zNplPp

    On Wed, Oct 10, 2012 at 9:41 AM, GGGo <ggco...@gmail.com <javascript:>>
    wrote:
    // begin code
    package main

    import "fmt"
    import "os/exec"
    import "log"
    import "runtime"

    var done = make(chan error)

    func watch() {
    for {
    select {
    case err := <-done:
    log.Printf("process done with error = %v", err)
    }
    }
    }

    func main() {
    go watch()
    var err error
    fmt.Println("Hello, playground")
    app1 := exec.Command("arecord")
    app2 := exec.Command("aplay")
    if app2.Stdin, err = app1.StdoutPipe(); err != nil {
    log.Fatal(err)
    }
    if err := app1.Start(); err != nil {
    log.Fatal(err)
    }
    if err = app2.Start(); err != nil {
    log.Fatal(err)
    }
    go func() {
    done <- app1.Wait()
    }()
    go func() {
    done <- app2.Wait()
    }()

    for{runtime.Gosched()}
    }
    //end code

    When you execute in a shell `arecord|aplay`, you can killall aplay and
    arecord will exit OR you can killall arecord and aplay will exit.
    I try to do the same thing in this example.
    If I killall arecord, aplay will exit. Good
    If I killall aplay, arecord stays there, and aplay exits. Not good.
    Any idea ?
    Thanks !

    --
    --
  • Skip Tavakkolian at Oct 10, 2012 at 11:11 pm
    your code needs to handle signals sent to it. crashing should be
    dealt with another way; i would not clean things up automatically
    after a crash because i want to see what caused it.

    here's a simplified version that handles signals.
    http://play.golang.org/p/qh5G16TiKS

    this book might be a good resource for you: Advanced Programming in
    the UNIX Environment (Stevens)
    On Wed, Oct 10, 2012 at 12:52 PM, GGGo wrote:
    I don't understand why the main func keep a duplicate of the file, but what
    you did solve my problem for sure. Thank you.

    I also notice something, if I run ./main in the shell, and type Ctrl+C, the
    main program exits and app1 and app2 exit too. Great. But If I killall main,
    app1 and app2 still running. (killall main or kill -9 PID or kill -2 PID)

    So it means if the main program crashes, app1 and app2 will continue to run.
    Right ? Is there something I can do to attach child commands to the main to
    prevent this ?

    On Wednesday, October 10, 2012 2:12:29 PM UTC-4, Skip wrote:

    close app2.Stdin after sub processes have started.

    in the first instance the reader gets an error because the writer has
    gone away and closed the write end and the reader exits. in the second
    case the writer doesn't get an error when a reader (aplay) has gone
    away because your main proc still has a duplicate of the file; the
    writer blocks when the pipe buffer is full.

    http://play.golang.org/p/Lps1zNplPp
    On Wed, Oct 10, 2012 at 9:41 AM, GGGo wrote:
    // begin code
    package main

    import "fmt"
    import "os/exec"
    import "log"
    import "runtime"

    var done = make(chan error)

    func watch() {
    for {
    select {
    case err := <-done:
    log.Printf("process done with error = %v", err)
    }
    }
    }

    func main() {
    go watch()
    var err error
    fmt.Println("Hello, playground")
    app1 := exec.Command("arecord")
    app2 := exec.Command("aplay")
    if app2.Stdin, err = app1.StdoutPipe(); err != nil {
    log.Fatal(err)
    }
    if err := app1.Start(); err != nil {
    log.Fatal(err)
    }
    if err = app2.Start(); err != nil {
    log.Fatal(err)
    }
    go func() {
    done <- app1.Wait()
    }()
    go func() {
    done <- app2.Wait()
    }()

    for{runtime.Gosched()}
    }
    //end code

    When you execute in a shell `arecord|aplay`, you can killall aplay and
    arecord will exit OR you can killall arecord and aplay will exit.
    I try to do the same thing in this example.
    If I killall arecord, aplay will exit. Good
    If I killall aplay, arecord stays there, and aplay exits. Not good.
    Any idea ?
    Thanks !

    --
    --
    --
  • GGGo at Oct 11, 2012 at 1:02 am
    Ok you used signal.Notify, really nice example. I like the way you handle
    the signals.

    I just found another way, and it seems to support crashing too.
    Just add:
    app1.SysProcAttr = &syscall.SysProcAttr{Pdeathsig:2}
    app2.SysProcAttr = &syscall.SysProcAttr{Pdeathsig:2} // Signal that the
    process will get when its parent dies (Linux only)

    Is a good one ?

    Thank you !
    On Wednesday, October 10, 2012 7:11:38 PM UTC-4, Skip wrote:

    your code needs to handle signals sent to it. crashing should be
    dealt with another way; i would not clean things up automatically
    after a crash because i want to see what caused it.

    here's a simplified version that handles signals.
    http://play.golang.org/p/qh5G16TiKS

    this book might be a good resource for you: Advanced Programming in
    the UNIX Environment (Stevens)

    On Wed, Oct 10, 2012 at 12:52 PM, GGGo <ggco...@gmail.com <javascript:>>
    wrote:
    I don't understand why the main func keep a duplicate of the file, but what
    you did solve my problem for sure. Thank you.

    I also notice something, if I run ./main in the shell, and type Ctrl+C, the
    main program exits and app1 and app2 exit too. Great. But If I killall main,
    app1 and app2 still running. (killall main or kill -9 PID or kill -2 PID)
    So it means if the main program crashes, app1 and app2 will continue to run.
    Right ? Is there something I can do to attach child commands to the main to
    prevent this ?

    On Wednesday, October 10, 2012 2:12:29 PM UTC-4, Skip wrote:

    close app2.Stdin after sub processes have started.

    in the first instance the reader gets an error because the writer has
    gone away and closed the write end and the reader exits. in the second
    case the writer doesn't get an error when a reader (aplay) has gone
    away because your main proc still has a duplicate of the file; the
    writer blocks when the pipe buffer is full.

    http://play.golang.org/p/Lps1zNplPp
    On Wed, Oct 10, 2012 at 9:41 AM, GGGo wrote:
    // begin code
    package main

    import "fmt"
    import "os/exec"
    import "log"
    import "runtime"

    var done = make(chan error)

    func watch() {
    for {
    select {
    case err := <-done:
    log.Printf("process done with error = %v", err)
    }
    }
    }

    func main() {
    go watch()
    var err error
    fmt.Println("Hello, playground")
    app1 := exec.Command("arecord")
    app2 := exec.Command("aplay")
    if app2.Stdin, err = app1.StdoutPipe(); err != nil {
    log.Fatal(err)
    }
    if err := app1.Start(); err != nil {
    log.Fatal(err)
    }
    if err = app2.Start(); err != nil {
    log.Fatal(err)
    }
    go func() {
    done <- app1.Wait()
    }()
    go func() {
    done <- app2.Wait()
    }()

    for{runtime.Gosched()}
    }
    //end code

    When you execute in a shell `arecord|aplay`, you can killall aplay
    and
    arecord will exit OR you can killall arecord and aplay will exit.
    I try to do the same thing in this example.
    If I killall arecord, aplay will exit. Good
    If I killall aplay, arecord stays there, and aplay exits. Not good.
    Any idea ?
    Thanks !

    --
    --
    --
  • Minux at Oct 12, 2012 at 4:35 pm

    On Thu, Oct 11, 2012 at 7:56 AM, GGGo wrote:

    I just found another way, and it seems to support crashing too.
    Just add:
    app1.SysProcAttr = &syscall.SysProcAttr{Pdeathsig:2}
    app2.SysProcAttr = &syscall.SysProcAttr{Pdeathsig:2} // Signal that the
    process will get when its parent dies (Linux only)
    I suggest you use syscall.SIGINT instead of 2 here.
    Is a good one ?
    Good if you don't (and won't) bother other OSes.

    --

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedOct 10, '12 at 4:49p
activeOct 12, '12 at 4:35p
posts6
users3
websitegolang.org

3 users in discussion

GGGo: 3 posts Skip Tavakkolian: 2 posts Minux: 1 post

People

Translate

site design / logo © 2022 Grokbase