Search code examples
cshellpipezshwaitpid

Why my pipe ends only when i send a SIGINT


Basicaly, im writing a shell in C.. Im trying to implement the pipe feature, which is almost done:

 > ls | cat -e | wc | wc -l
 > 1

But i have a problem when trying to pipe a more slower/longer execution.

Indeed, when i try to pipe the result of 'cat /dev/urandom', it basicly waits...

> cat /dev/urandom | cat
>

But, when i send a SIGINT (with ctrl + c) to stop it, then it prints on STDOUT the resulted buffer..

when i ctrl + c , cat /dev/urandom

So my question is: where should i be looking at to try fix this ?

PARTS OF MY PIPE EXECUTION:

    int         exec_apipe(t_me *me, t_node *curs, int is_last)
{
    int     pfd[2];
    int     pid;

    if (pipe(pfd) == -1 || !curs)
        return (0);
    if (!(curs->pid = fork()))
    {
        dup2(me->fd_in, 0);
        me->fd_in > 0 ? close(me->fd_in) : 0;
        if (!is_last)
            dup2(pfd[1], 1);
        else if (curs->parent->parent && curs->parent->parent->fd_out >= 0)
            dup2(curs->parent->parent->fd_out, 1);
        close(pfd[0]);
        exec_mpipe(me, curs);
        exit(-1);
    }
    else if (curs->pid > 0)
    {
        waitpid(curs->pid, &(curs->ret), WUNTRACED);
        handle_pid(me, curs->ret);
        close(pfd[1]);
        me->fd_in = pfd[0];
    }
    return (pid >= 0 ? 1 : -1);
}

I hope someone will understand what im saying, and maybe can help.. Thanks


Solution

  • You need to start all the programs in your pipeline before you wait for any of them to complete.

    Your shell implementation is waiting for each pipeline element to finish before it starts the next one. But /dev/urandom is an endless stream; cat /dev/urandom will run until killed. So the second cat never gets started until you control-C the first one.