0
votes

I try to understand the topic of redirection of child processes Standard Output to pipe, that parent process could read it and face with very strange behavior. In the example parent process fork 3 child processes that do simple file search and want to get the output. I receive only first result. What could be wrong with this example?

The code looks like this:

char * searches[] = {
            ".bashrc",
            "NM34_x64.exe",
            "blacklist.sh"
    };
    int fd[2];
    if (pipe(fd) == -1) {
        error("Can't create the pipe");
    }
    __pid_t pids[sizeof(searches)/sizeof(char*)];

    for(int i = 0; i < sizeof(searches)/sizeof(char*); i++){
        __pid_t pid = fork();

        switch (pid) {
            case -1 :
                // ERROR CASE
                error("Failed to make a child process");
                break;
            case 0 :
                // CHILD CASE
                // 1. Redirect Standard Output to pipe
                dup2(fd[1], 1);
                close(fd[0]);
                // 2. Execute command
                if (execl("/usr/bin/find", "/usr/bin/find", "/home", "-name", searches[i], NULL) == -1)
                    error("Failed to execute the command in the child process");
                break;
            default:
                // PARENT CASE
                printf("Created child process with pid %d\n", pid);
                pids[i] = pid;
                // 1. Wait for PID to finish
                int status;
                waitpid(pids[0], &status, 0);
                if (status == -1)
                    error("Failed to wait the child PID");
                printf("Process %d finish his work\n", pids[i]);
                // 2. Redirect pipe to Standard Input
                dup2(fd[0],0);
                close(fd[1]);
                // 3. Read Standard Input
                char line[255];
                while (fgets(line,255,stdin)) {
                    printf("%s", line);
                }
                break;
        }
    }
    return 0;

Here is the output:

Created child process with pid 5063
Process 5063 finish his work
/home/user/.bashrc
Created child process with pid 5064
Process 5064 finish his work
Created child process with pid 5065
Process 5065 finish his work
1
The general pattern is close(fd[0]); dup2(fd[1], 1); close(fd[1]). You are leaving file descriptors open.William Pursell
The parent closes fd[1] after waiting for the first child. When the second child is forked, fd[1] is already closed and can't be written to. You can run this under strace -f to watch the 2nd and 3rd child processes failing to writeUseless
But how to better solve this?javadev

1 Answers

0
votes

When you are using a pipe for inter process communication read the input from the pipe to main process directly instead of redirecting it again to standard input and read it in the main process.