Search code examples
ctimeunix-socket

C- program using fork won't exit after user inputs 'exit'


We were tasked to create a two-way communication simulation in one c code. It's my first time dabbling with this kind of code so I have created this simple code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include<wait.h>
int main(void)
{
    pid_t pid;
    char buf[1024];
    char cp[50];
    char ex[100]="exit";
    int readpipe[2];
    int writepipe[2];
    long int a;
    int b;
    a=pipe(readpipe);
    b=pipe(writepipe);
    int test=1;
    int length;

    if (a == -1) { perror("pipe"); exit(EXIT_FAILURE); }
    if (b == -1) { perror("pipe"); exit(EXIT_FAILURE); } 
    fflush(stdin);
    pid=fork();
    if(pid==-1)
        {
            printf("pid:main");
            exit(1);
        }
    while(test==1)
        {
            if(pid==0)
                { 
                    close(readpipe[1]);
                    close(writepipe[0]);
                    if(read(readpipe[0],buf,sizeof(buf)) < 0)
                        {
                            exit(1);
                        }
                    printf("\nSEND TO USER 1:");
                    fflush(stdin);
                    fgets(cp, 50, stdin);
                    length = strlen(cp);
                    if(cp[length-1] == '\n') {
                        --length;
                        cp[length] = '\0';
                    }   
                    if(strcmp(cp,ex)==0) {
                        test=0;
                        break;
                    }
                    if(write(writepipe[1],cp,strlen(cp)+1) < 0)
                        {
                            exit(1);
                        }
                }
            else
                {
                    close(readpipe[0]);
                    close(writepipe[1]);
                    printf("\nSEND TO USER 2:");
                    fflush(stdin);
                    fgets(cp, 50, stdin);
                    length = strlen(cp);
                    if(cp[length-1] == '\n') {
                        --length;
                        cp[length] = '\0';
                    }   
                    if(strcmp(cp,ex)==0) {
                        test=0;
                        break;
                    }
                    if(write(readpipe[1],cp,strlen(cp)+1) < 0)
                        {
                            exit(1);
                        }        

                    if(read(writepipe[0],buf,sizeof(buf)) < 0)
                        {
                            exit(1);
                        }        
                }
        }
    close(readpipe[1]);
    close(writepipe[0]);
    close(readpipe[0]);
    close(writepipe[1]);
    return 0;
}

The program terminates when USER 1 or USER 2 inputs exit. However....

The error is that whenever I press exit, it will print the "SEND TO USER x" first then proceeds to exit. How can I fix this? Any help? Thanks.


Solution

  • When you type exit into the sending process, it breaks out of the loop, closes its end of the pipes, and exits.

    When the other process tries to read from the pipe, it will get an EOF, which is indicated by read() returning 0. But your code never checks for this, it only exits when read() or write() returns a negative value to indicate an error (EOF is not an error). So it goes back to the top of the loop and asks for input to send to the other process. When it tries to write to the closed pipe it will get an EPIPE error or a SIGPIPE signal, and it will then exit.

    Change your reading code to:

    int n = read(readpipe[0],buf,sizeof(buf));
    if (n == 0) {
        break;
    } else if (n < 1) {
        exit(1);
    }