0

In these snippets the go program tries to write to C program's stdin. The problem is that the c program starts an infinite loop after the go loop finishes.

main.c

#include <stdio.h>
#include <stdlib.h>


int main(){
    int age;
    char name[8]; 

    for(;;)
    {
    scanf(" %s : %d\n",&name, &age);
    printf("%s : %d\n",name, age);
    }
    return 0;
}

run/main.go

func main() {

    proc := exec.Command("../main")
    stdin, err := proc.StdinPipe()
    if err != nil {
        fmt.Println(err) 
    }

    defer stdin.Close()

    proc.Stdout = os.Stdout
    proc.Stderr = os.Stderr

    fmt.Println("START")                      
    if err = proc.Start(); err != nil { 
        log.Fatal("An error occured: ", err)
    }

    for i := 0; i < 500; i++ {
        io.WriteString(stdin, fmt.Sprintf("hello : %d\n", i))
        //How to wait here and read from printf()?
    }

    //proc.Process.Kill() Here proc gets killed too fast

    fmt.Println("END")
}

When killed, process doesn't complete it's output

Output

START
END
hello : 497
hello : 498
hello : 499
hello : 499 

Output Expected

START
....
hello : 497
hello : 498
hello : 499
END
9
  • 2
    check for the scanf return value Commented Feb 9, 2022 at 19:40
  • 2
    You forwarded the stdout of the child process to the standard output of your process. If you don't want that, don't do that and read from the proc.Stdout. Or have the child program send a signal when it's done. Commented Feb 9, 2022 at 19:42
  • 1
    Remove the \n from the scanf: stackoverflow.com/questions/15443483/using-n-in-scanf-in-c Commented Feb 9, 2022 at 19:43
  • 1
    You need to coordinate with the child process in some way, read stdout, have it exit if you close stdin, etc. The C program enters an infinite loop when you close stdin without the Go program too, because that's what you wrote in the C program. Commented Feb 9, 2022 at 19:44
  • 2
    for(;;) is an infinite loop since there's nothing in it to break out. Use the return value from scanf to determine that it failed and break there. Commented Feb 9, 2022 at 19:47

1 Answer 1

0

After reading the comments and few more searching I have worked it out. On C program I removed \n from scanf() and added fflush(stdout) after printf. According to this page I changed them to these:

int main(){
    int age;
    char name[8]; 

    int ret;

    for(;;)
    {
    ret= scanf("%s : %d",&name, &age);
    if (ret == -1) {
        break;
    }
    printf("%s : %d\n",name, age);

    fflush(stdout);
    }
    
    return 0;
}
func main(){
    proc := exec.Command("../main")

    stdin, err := proc.StdinPipe()
    if err != nil {
        fmt.Println(err)
    }

    reader, err := proc.StdoutPipe()
    if err != nil {
        fmt.Println(err)
        return
    }

    scanner := bufio.NewScanner(reader)
    resp := make(chan string)

    go func() {
        for scanner.Scan() {
            resp <- scanner.Text()
        }
    }()

    err = proc.Start()
    if err != nil {
        fmt.Fprintln(err)
        return
    }
    fmt.Println("START")

    for i := 0; i < 500; i++ {
        io.WriteString(stdin, fmt.Sprintf("hello : %d\n", i))

        v := <-resp
        print(v+"\n")

    }

    err = proc.Process.Kill()

    if err != nil {
        fmt.Fprintln(err)
        return
    }
    fmt.Println("END")

}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.