Search code examples
cpipeforkexec

fork() child exec command outputting weirdly


I am trying to do ls -la | wc

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
    
int main(int argc, char **argv)
{
    int pipes=3;
    char *ls[] = {"ls","-la",NULL};
    char *wc[] = {"wc",NULL};
    char *base64[] = {"base64","-w0",NULL};
    //char **commands[] = {ls,wc,base64};

    int fds[pipes][2];
    for(int i=0;i<pipes;i++)
    {
        int err = pipe(fds[i]);
        if(err == -1)
        {
            perror("Pipe failed.\n");
        }
    }
    int status;
    pid_t childPid;
    //Child 1.
    if((childPid = fork()) == 0)    
    {
        dup2(fds[0][1],1);
        for(int i=0;i<pipes;i++)
        {
            close(fds[i][0]); 
            close(fds[i][1]);
        }
        execvp(ls[0],ls);
        exit(0);
    }
    else if(childPid == -1)
    {
        perror("Child 1 failed.\n");
    }
    // Second child.
    if((childPid = fork()) == 0)
    {
        dup2(fds[0][0],0);
        for(int i=0;i<pipes;i++)
        {
            close(fds[i][0]); 
            close(fds[i][1]);
        }
        execvp(wc[0],wc);
    }
    else if(childPid == -1)
    {
        perror("Child 2 failed.\n");
    }

    for(int i=0;i<pipes;i++)
    {
        close(fds[i][0]);
        close(fds[i][1]);
    }
    waitpid(childPid,&status,WUNTRACED|WNOHANG);
    return 0;
}

out expect:

root@danial#gcc -o pip pip.c

root@danial#./pip

10      83     436

output I am getting:

root@danial#./pip

root@danial# 10 83 436

cursor stays here until I press enter key.

I tried doing this without pipes just wrote a simple program:

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

int main(int argc, char **argv)
{
    if(fork() == 0)
    {
        execlp("ls","ls","-la",NULL);
        exit(0);
    }
    return 0;
}

and samething happend:

root@danial#./test

root@danial#total 84

drwxr-xr-x 3 root root 4096 Mar 30 06:49 .

drwxr-xr-x 9 root root 4096 Mar 29 09:33 ..

-rwxr-xr-x 1 root root 16960 Mar 30 06:49 pip

-rw-r--r-- 1 root root 1310 Mar 30 06:48 pip.c


Solution

  • The problem is this

    waitpid(childPid,&status,WUNTRACED|WNOHANG);
    

    With the WNOHANG you tell waitpid to poll the status, and then return immediately withoput actually waiting.

    When the waitpid call returns, you exit the parent process, leaving your two child-processes orphaned.

    And what happens when the parent process exiting is that its parent process (the shell) taking over and printing the prompt. Then your child-processes prints their output. The Enter key you press to "clear" the output is simply empty input for the shell.

    You need to wait for both your child processes.