Search code examples
cforkproducer-consumer

C pipe: Bad file descriptor


I have the simple producer consumer program in C try to solve it with fork I get error exactly when producer tries to write on pipe: I have wrote another program with the same logic but this one does not give me any clue to know why?

Producer failed to write item on pipe: Bad file descriptor

Anyone have idea why I get this error? Thanks

#define READ 0
#define WRITE 1
int mutex = 1, full = 0, empty = BUFFER_SIZE, x = 0;

void consumer();

void producer();

int wait_(int);

int signal_(int);

int pipefd[2];

int main() {
    printf("Starting producer-consumer problem!\n");
    //We intend to run the producer in parent process and the consumer in the child process
    if (pipe(pipefd) == -1) {       /* An error has occurred. */
        fprintf(stderr, "%s", "The call to pipe() has failed.\n");
        exit(EXIT_FAILURE);
    }
    for (int j = 0; j < sizeof(pipefd); j++) {
        if (pipe(&pipefd[j]) < 0) { //Initialize each pipe appropriately
            perror("Error in making pipe...");
        }
    }
    pid_t pid = fork();
    if (pid < 0) {
        perror("**********Error in creating fork()!**************\n");
        exit(STDERR_FILENO);
    } else if (pid == 0) {
        consumer();//We intend to run the consumer in child
    } else {
        producer();//We intend to run the producer in parent
    }
    return 0;
}

int wait_(int s) {
    return (--s);
}

int signal_(int s) {
    return (++s);
}

void producer() {
    printf("Starting Producer\n");
    //while (1) {
    //sleep(1);
    if (close(pipefd[READ]) != 0) {
        perror("Error in closing reading pipe");
    }
    if (write(pipefd[WRITE], &full, 1) < 0) {
        perror("Producer failed to write item on pipe");
    }
    if ((mutex == 1) && (empty != 0)) {
        mutex = wait_(mutex);
        full = signal_(full);
        empty = wait_(empty);
        x++;
        printf("Producer produces the item %d\n", x);
        mutex = signal_(mutex);
    }
    if (close(pipefd[WRITE]) != 0) {
        perror("Error in closing writing pipe");
    }
    //}
}

void consumer() {
    printf("Starting Consumer\n");
    //while (1) {
    //sleep(1);
    int status = 0;
    wait(&status);              /* wait for all children to return back the result */
    if (close(pipefd[WRITE]) != 0) {
        perror("Error in closing reading pipe");
    }
    if (read(pipefd[READ], &full, 1) > 0) {
        printf("Consumer\t%d\n", full);
    }
    if ((mutex == 1) && (full != 0)) {
        mutex = wait_(mutex);
        full = wait_(full);
        empty = signal_(empty);
        printf("Consumer consumes item %d\n", x);
        x--;
        mutex = signal_(mutex);
    }
    if (close(pipefd[READ]) != 0) {
        perror("Error in closing reading pipe");
    }
    //}
}

Solution

  • The sizeof operator returns the size in bytes. So on a typical system where an int is four bytes, sizeof(pipefd) would result in the value 8. Which is not the correct number of elements for your loop.

    Also, pipe(&pipefd[j]) is not correct either. The two pipes in pipefd are already initialized "appropriately". There's no need for any more initialization. Especially since in both this and the previous case you will have undefined behavior.