0
votes

I'm having trouble with a particular command line for my shell: base64 /dev/urandom | head -c 1000

As you can see the first process base64 writes never-ending characters into the pipe and head will read the first 1000 characters and then exit properly.

I know the pipe's fd are duplicated in every child processes and that if you close them in the parent they will not be closed in the child's causing the problem that I have. When closing the reading end of the pipe in the parent it will not send a SIGPIPE signal terminating the first process because it will still be open in the child.

So, basically, in case of a never-ending process, it will try to write into the pipe successfully because in the fork, the reading end of the pipe will never be closed.

So how can I successfully exit the first process when the second one has finished to read in the pipe, in other words, how can I share the SIGPIPE signal between children processes.

This code is the part where I do the piping, forking and waiting:

void            exec_process(t_shell *sh, t_job *job, int *iofile)
{
    t_parse *parse;

    parse = init_parse(sh, job->process->cmd);
    if (check_builtins(parse->argv[0]))
    {
        if (iofile[0] != 0)
            job->process->stdio[0] = iofile[0];
        if (iofile[1] != 1)
            job->process->stdio[1] = iofile[1];
        launch_builtin(sh, parse, job);
    }
    else if ((job->process->pid = fork()) == 0)
    {
        if (iofile[0] != 0)
            job->process->stdio[0] = iofile[0];
        if (iofile[1] != 1)
            job->process->stdio[1] = iofile[1];
        launch_bin(parse, job);
    }
    free_parse(&parse);
    if (iofile[0] != 0)
        close(iofile[0]);
    if (iofile[1] != 1)
        close(iofile[1]);
 }

static void     launch_process(t_shell *sh, t_job *job)
{
    t_process   *process;
    int         iofile[2];
    int         pipefd[2];
    int         i;

    process = job->process;
    iofile[0] = 0;
    i = get_num_process(job->process);
    while (job->process)
    {
        if (job->process->next)
        {
            pipe(pipefd);
            iofile[1] = pipefd[1];
        }
        else
            iofile[1] = 1;
        exec_process(sh, job, iofile);
        iofile[0] = pipefd[0];
        job->process = job->process->next;
     }
     job->process = process;
     wait_for_job(sh, job, i);
 }

I have one parent and 2 children that are only link to the parent.

Any suggestions? Thank you

1

1 Answers

1
votes

each process must close the end of the pipe it doesn't use so that when other process terminates read or write call fails.