'C++ Pipe, dup2, execlp hangs

So I am trying to run 3 commands in a sequential way.

ls -l / | grep a | sort -r

However, my code seems to hang the process. I know that this usually indicated an unhandled pipe. but I can't seem to find the problem, I have closed all possible file descriptors that I could find.

Code may have some meaningless lines like closing the same FD twice, which I added while trying to fix it

#include <iostream>
#include<unistd.h>
#include <sys/wait.h>
using namespace std;
    
#define pipeWrite 1
#define pipeRead 0
    
// Main Function
int main() {
    //Command to run: ls -l / | grep a | sort -r | wc > count.txt
    // Total 4 commands to run, so 4 child processes.
    
    pid_t c1,c2,c3,c4;
    // File Descriptors
    int pipeFD_1[2];
    int pipeFD_2[2];
    
    pipe(pipeFD_1);
    
    // To execute ls -l
    c1 = fork();
    
    // Child
    if (c1 == 0) {
        // Closing input end
        close(1);
        dup(pipeFD_1[1]);
    
        close(pipeFD_1[0]);
        close(pipeFD_1[1]);
        // Running command
        execl("/bin/ls", "ls", "-l", "/",NULL);
    }
    
    pipe(pipeFD_2);
    c2 = fork();
    
    if (c2 == 0) {
        // Closing output end
        close(0);
        dup(pipeFD_1[0]);
    
        close(1);
        dup(pipeFD_2[1]);
               
        close(pipeFD_1[0]); 
        close(pipeFD_1[1]);
        close(pipeFD_2[0]); 
        close(pipeFD_2[1]);
        // Running command
        execl("/bin/grep", "grep", "a", NULL);
    }
    
    //Closing pipe 1.
    close(pipeFD_1[0]);
    close(pipeFD_1[1]);
    
    c3 = fork();
    
    if (c3 == 0) {
        // Closing out end
        close(0);
        dup(pipeFD_2[0]);
                
                
        close(pipeFD_2[0]);
        close(pipeFD_2[1]);
        // Running command
        execl("/bin/sort", "sort", "-r", NULL);
    }
    
    // Since exec auto exits the child process. No need to put else.
    // Closing output end
    waitpid(-1, NULL, 0);
    waitpid(-1, NULL, 0);
    waitpid(-1, NULL, 0);
    exit(0);
}

EDIT: Fixed by adding 2 more lines after the third fork, closing FDs for pipe2 (for parent).



Solution 1:[1]

Thank you Barmar and ItsHoney for your valuable discussions. Posting them as answer to help other community members.

Fixed by adding 2 more lines after the third fork, closing FDs for pipe2 (for parent).

#include <iostream>
#include<unistd.h>
#include <sys/wait.h>
using namespace std;
    
#define pipeWrite 1
#define pipeRead 0
    
// Main Function
int main() {
    //Command to run: ls -l / | grep a | sort -r | wc > count.txt
    // Total 4 commands to run, so 4 child processes.
    
    pid_t c1,c2,c3,c4;
    // File Descriptors
    int pipeFD_1[2];
    int pipeFD_2[2];
    
    pipe(pipeFD_1);
    
    // To execute ls -l
    c1 = fork();
    
    // Child
    if (c1 == 0) {
        // Closing input end
        close(1);
        dup(pipeFD_1[1]);
    
        close(pipeFD_1[0]);
        close(pipeFD_1[1]);
        // Running command
        execl("/bin/ls", "ls", "-l", "/",NULL);
    }
    
    pipe(pipeFD_2);
    c2 = fork();
    
    if (c2 == 0) {
        // Closing output end
        close(0);
        dup(pipeFD_1[0]);
    
        close(1);
        dup(pipeFD_2[1]);
               
        close(pipeFD_1[0]); 
        close(pipeFD_1[1]);
        close(pipeFD_2[0]); 
        close(pipeFD_2[1]);
        // Running command
        execl("/bin/grep", "grep", "a", NULL);
    }
    
    //Closing pipe 1.
    close(pipeFD_1[0]);
    close(pipeFD_1[1]);
    
    c3 = fork();
    
    if (c3 == 0) {
        // Closing out end
        close(0);
        dup(pipeFD_2[0]);
                
                
        close(pipeFD_2[0]);
        close(pipeFD_2[1]);
        // Running command
        execl("/bin/sort", "sort", "-r", NULL);
    }
    
    // Since exec auto exits the child process. No need to put else.
    // Closing output end
    waitpid(-1, NULL, 0);
    waitpid(-1, NULL, 0);
    waitpid(-1, NULL, 0);
    exit(0);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 MadhurajVadde-MT