Search code examples
cglibcmkfifo

Reader-process termination on FIFO-file closing


I've written a simple reader-writer pair of programs. Writer creates/opens a FIFO-file and is constantly writing a string into it. The reader is just reading it and writing to stdout. The reader does so only for 10 times and then quits. Surprisingly (for me) the writer almost immediately exits too. It does not just go out of writing loop, it seems to jump out of it, I can tell it by not seeing the final "byebye" on the screen. I could sort of accept such behaviour, but I still can't understand why. Could someone please kindly share their knowledge with me?

/* writer code */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
    char msg [] = "Leo_Tolstoy";

    size_t len = strlen("Leo_Tolstoy");

    if (mkfifo ("myfifo", 0600) != 0) {
        perror ("creating fifo");
    }
    int fd;
    if ( (fd = open ("myfifo", O_WRONLY)) == -1) {
        perror ("opening fifo");
        exit (1);
    }
    while (1)
    {
        int r = write (fd, msg, len);
        if (r == -1)
            perror ("writing");
        sleep(1);
    }
    printf ("byebye\n");
    close (fd);
    return 0;
}
/* reader code */
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/shm.h>

int main()
{
    char buf[50];

    printf ("bef opening\n");
    int fd = open ("myfifo", O_RDONLY);
    if (fd == -1) {
        perror ("opening fifo");
        exit (1);
    }

    printf ("bef reading\n");
    int cnt=0;
    while (cnt < 10)
    {
        int r = read (fd, buf, 50);
        if (r == 0)
            break;
        if (r == -1)
            perror ("reading");
        write (1, buf, r);
        cnt++;
    }
//  close (fd);
    return 0;
}

Solution

  • When the exits (after 10 iterations), the writer receives a SIGPIPE due to the read end being closed. So, the default action for the signal SIGPIPE is executed which to terminate the program. That's why you don't see the final printf() is not executed.

    Instead you could ignore (SIG_IGN) the signal SIGPIPE in the writer by calling sigaction() and then handle the write error yourself.