Search code examples
clinuxiopipefork

Trouble getting child processes to communicate with each other


I am new to linux programming. I am trying to spawn two child processes and connect them through pipe. The generating child process should generate random numbers and the other child process should run a binary which takes those two numbers and finds their greatest common divider. The binary already works well with stdin so I am trying to redirect it to read end of a pipe. Similarly I do that with generating process with stdout connected to write end of a pipe.

But I think I didn't do good job wiring it together, because there is no output. Any help would be much appreciated!

I didn't find many materials on this online so suggesting those would also help a lot. Thanks.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

#define exec_path "nsd"

void create_pipe(int *proc_pipe);

int create_proc();

void sig_handler(int sig);

int main() {
    int proc_pipe[2];
    pid_t gen_proc;
    pid_t nsd_proc;
    int proc_stat;

    create_pipe(proc_pipe);

    gen_proc = create_proc();

    if (gen_proc == 0) {
        // child exec
        struct sigaction act;
        act.sa_handler = &sig_handler;

        close(proc_pipe[0]);
        dup2(proc_pipe[1], 1);
        close(proc_pipe[1]);

        while (1) {
            printf("%d %d\n", rand() % 4096, rand() % 4096);
            sleep(1);
            if (sigaction(SIGTERM, &act, NULL) == -1) exit(2);
        }
    } else {
        nsd_proc = create_proc();

        if (nsd_proc == 0) {
            // child exec
            close(proc_pipe[1]);
            dup2(proc_pipe[0], 0);
            close(proc_pipe[0]);

            execl(exec_path, "nsd", (char *) NULL);
        } else {
            close(proc_pipe[0]);
            close(proc_pipe[1]);
            sleep(5);
            kill(gen_proc, SIGTERM);
            wait(&proc_stat);
            if (proc_stat != 0) {
                perror("ERROR");
                return 1;
            } else {
                printf("OK\n");
                return 0;
            }
        }
    }
}

void sig_handler(int sig) {
    if (sig == SIGTERM) {
        perror("GEN TERMINATED");
        exit(0);
    }
}

pid_t create_proc() {
    pid_t pid = fork();
    if (pid == -1) {
        perror("error forking new process");
        exit(2);
    }
    return pid;
}

void create_pipe(int *proc_pipe) {
    if (pipe(proc_pipe) == -1) {
        perror("failed to create pipe");
        exit(2);
    }
}

Solution

  • printf doesn't call write until it fills a buffer. You aren't giving your child enough time to fill that buffer. Add fflush(stdout) before the child goes to sleep so some data is actually written into the pipe.