Bad file descriptor error when implementing piping in C

Kai

I am trying to implement a sample shell like program which executes the command ls | wc

Using pipes to implement the command. When I execute the command I get the following error.

wc: standard input: Bad file descriptor 0 0 0 wc: -: Bad file descriptor

Please take a look at the code and provide inputs Note: 1) parse is a library which takes in the input typed and returns each command as a linked list with args and necesary data. Parse is working fine 2) I am executing each command in a different subprocess hence the fork

#include <stdio.h>
#include <stdlib.h>
#include "parse.h"

int pip[3][2];
int main(int argc, char *argv[], char *envp[])
{
    Pipe p; 
    Cmd c;
    pipe(pip[0]);
    pipe(pip[1]);   
    pid_t pid;
    pid=fork();
    char *host = "armadillo";
    printf("%s%% ", host);
    p = parse();
    c=p->head;  
    printf("1 \n");
    pid=fork();

    if(pid==0)
    {
        close(pip[0][0]);
        close(STDOUT_FILENO);
        dup2(pip[0][1],STDOUT_FILENO);
        execvp(c->args[0],c->args);
    }
    else
    {
        waitpid(pid,NULL,0);
    }
    printf("2 \n");

    close(pip[0][1]);
    close(pip[0][0]);

    c=c->next;
    printf("%s \n",c->args[0]);
    pid=fork();
    if(pid==0)
    {
        close(STDIN_FILENO);
        dup2(pip[0][0],STDIN_FILENO);
        close(pip[0][1]);
        execvp(c->args[0],c->args);
    }
    else
    {   
        waitpid(pid,NULL,0);
        close(pip[0][1]);
        close(pip[0][0]);
    }

}
sjnarv

I took the lazy way out, and wrote my own rather than fix other code. Treat this as "yet another pipe-fitting example in C", but it might help point out the issues with OP's code.

/*
 * hard-wired example program exploring how to implement
 *
 *     system("ls | wc");
 *
 * using calls to pipe(2), fork(2), execvp(2) and wait(2)
 */

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

static void
do_close(int fd)
{
    if (close(fd) == -1) {
        perror("close");
        exit(1);
    }
}

static void
do_execvp(char *const cmd[])
{
    execvp(cmd[0], cmd);

    /*
     * if execvp returns in this text, an error occured.
     */

    perror("execvp");

    exit(1);
}

static void
dup_and_exec(int fd, int *pp, char *const cmd[])
{
    if (dup2(pp[fd], fd) == -1) {
        perror("dup2");
        exit(1);
    }

    do_close(pp[0]);
    do_close(pp[1]);

    do_execvp(cmd);
}

int
main(void)
{
    char *const ls_cmd[] = { "ls", 0 };
    char *const wc_cmd[] = { "wc", 0 };

    int fds[2];

    int w_stat;
    pid_t ls_pid, wc_pid, w_pid;

    /* create a single pipe to connect our writer and reader processes */

    if (pipe(fds) == -1) {
        perror("pipe");
        exit(1);
    }

    /* create the writer process: ls */

    ls_pid = fork();

    if (ls_pid == -1) {
        perror("fork");
        exit(1);
    }

    if (ls_pid == 0) {
        /* this is the child - do the "ls" command */

        dup_and_exec(1, fds, ls_cmd);   /* no return from here */
    }

    /* create the reader process: wc */

    wc_pid = fork();

    if (wc_pid == -1) {
        perror("fork");
        exit(1);
    }

    if (wc_pid == 0) {
        /* this is the child - do the "wc" command */

        dup_and_exec(0, fds, wc_cmd);   /* no return from here */
    }

    /* parent process */

    /*
     * It's important to close the pipe completely in the parent,
     * so (in particular) there's no process that could be an
     * additional writer to the "write" side of the pipe.
     *
     * We need to arrange things so that our reader process (the "wc"
     * process in this example) will see EOF when the only writer (the
     * "ls" process) closes its output and exits.
     *
     * If this parent process does not close the write side of the pipe,
     * it remains open, since it's shared across fork(2), so the reader
     * (wc) won't ever see EOF and exit, and this parent process won't
     * ever see the wc exit, and everything hangs.
     *
     * The core problems will have started with the parent, which all
     * children know to be true.
     *
     * The next lines also close the "read" side of the pipe, which
     * is a bit cleaner, but won't affect proper operation of this
     * sample program. But closing all un-needed file descriptors is
     * good hygiene: for longer running applications, or for library
     * code that could be called from longer running programs, avoiding
     * any leaks of file descriptors is a good thing.
     */

    do_close(fds[0]);
    do_close(fds[1]);

    while ((w_pid = wait(&w_stat)) > 0) {
        printf("%s process exited", w_pid == ls_pid ? "ls" : "wc");
        if (WIFEXITED(w_stat)) {
            printf(" (status %d)", WEXITSTATUS(w_stat));
        }
        fputs("\n", stdout);
    }

    if (w_pid == -1 && errno != ECHILD) {
        perror("wait");
        exit(1);
    }

    return 0;
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

ERROR on accept: Bad file descriptor

How to use a file pointer of a file descriptor with multiple child processes without getting "Bad file descriptor" error in C?

Bad file descriptor error when trying to associate fmemopen file descriptor with stdin

C pipe: Bad file descriptor

systrace error: Bad file descriptor (9)

Perl select return "bad file descriptor" error

fork and pipe bad file descriptor error

Flutter bad file descriptor error on MacOS

Bad file descriptor error [Errno 9]

bad file descriptor: error on accept() (socket)

Getting "Bad file descriptor" error during tar

Git Initial Push Bad File Descriptor Error

'Bad file descriptor' error on an accepted socket

Bad file descriptor when using Pyside

Bad file descriptor when using fdopen?

Why am I getting a "bad file descriptor" error when writing file in rust?

Bad file descriptor error when closing pipe file descriptors after forking

Why do I get a Bad File Descriptor error when writing to opened File?

bad file descriptor in c program with forks

C : (standard input): Bad file descriptor

error: file write error: Bad file descriptor fatal: unable to write sha1 file when using git add

How to fix "Error reading from socket - bad file descriptor" while in thread on Linux using C?

Why am I getting a bad file descriptor error while calling a C function to write to log?

Golang bad file descriptor

write(): Bad file descriptor

Bad file descriptor fgets

I/O Error: Bad File Descriptor, can not save python file

OpenCV - linker error when implementing a new descriptor - rotation invariant BRIEF

Bad file descriptor after recursive function to open file in C