Search code examples
cpipeforkipc

C - Sending data back and forth between processes


I am working on the program below. What it is supposed to do is get the random int from the child process, and depending on the item_count variable, return the appropriate message to the child through the use of pipes. The problem is that I get a lot of unexpected behavior when executing, see below. myCatalog is a struct.

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

struct catalog {
    char description[128];
    int price;
    int item_count;
};

int main() {
    int i, j, k, fd1[5][2], fd2[5][2];
    struct catalog myCatalog[3];
    pid_t pid;
    int itemNo;
    char message[24];
    char messageFailure[] = "Failure.", messageSuccess[] = "Success!";;        

 

    for(i = 0; i < 5; i++) {
        if(pipe(fd1[i]) == -1) {
                printf("Error opening pipe 1!\n");
                exit(1);
        }

        if(pipe(fd2[i]) == -1) {
            printf("Error opening pipe 2!\n");
            exit(1);
        }

        pid = fork();

        if(pid == 0) { //Child
            time_t t;
            srand((int)time(&t) % getpid());
            
            close(fd1[i][0]);  //Close reading end of fd1
            close(fd2[i][1]);  //Close writing end of fd2
            
            for(k = 0; k < 10; k++) {
                itemNo = rand() % 21;
                write(fd1[i][1], &itemNo, sizeof(int));
                sleep(1);
                read(fd2[i][0], message, sizeof(message));
                printf("%s\n", message);
            }
            printf("Hello from child process %d\n", getpid());
            close(fd1[i][1]);
            close(fd2[i][0]);
            exit(0);
        }
        else if(pid > 0) { //Parent
            int item;

            close(fd1[i][1]);  //Close writing end of fd1
            close(fd2[i][0]);  //Close reading end of fd2

            if(i == 0) {
                for(j = 0; j < 20; j++) {
                    snprintf(myCatalog[j].description, sizeof(myCatalog[j].description), "Item #%d", j);
                    myCatalog[j].price = (rand() % 10) + 1;
                    myCatalog[j].item_count = 2;
                }
                for(j = 0; j < 20; j++) {
                    printf("Description: %s\n", myCatalog[j].description);
                    printf("Price: %d\n", myCatalog[j].price);
                    printf("Count: %d\n", myCatalog[j].item_count);
                }   
            }
            for(j = 0; j < 10; j++) {
                read(fd1[i][0], &item, sizeof(int));
                printf("%d\n", item);
                myCatalog[item].item_count = myCatalog[item].item_count - 1;
                if(myCatalog[item].item_count <= 0) {
                    write(fd2[i][1], messageFailure, sizeof(messageFailure));
                }
                else {
                    write(fd2[i][1], messageSuccess, sizeof(messageSuccess));                
                }
                sleep(1);
            }
            printf("Hello from parent process %d\n", getpid());
            close(fd1[i][0]);
            close(fd2[i][1]);
            wait(NULL);
        }
        else {
            printf("Error forking!");
            exit(1);
        }

    }
    return 0;
}

A sample output for one child process looks like this:

Hello from parent process 11868
Hello from child process 11890
6
Success!
4
Success!
3
Success!
4
3
16
Success!
14
3
6
3
18
3
20
3
18
3

What it should do is print the number, then either success or failure etc. Also, it shoots out 13 numbers sometimes instead of 10. The question is, where is the problem? Is it my piping? Is my loop usage completely wrong? Any help would be greatly appreciated.


Solution

  • This certainly doesn't look right. Accessing myCatalog[n] for n > 2 invokes undefined behavior.

      struct catalog myCatalog[3];
      ...
      for(j = 0; j < 20; j++) {
              printf("Description: %s\n", myCatalog[j].description);