tags:

views:

159

answers:

2

I am trying to use a named pipe for communication within a process. Here is the code

#include <stdio.h>
#include <fcntl.h>
#include <signal.h>

void sigint(int num)
{
    int fd = open("np", O_WRONLY);
    write(fd, "y", 1);
    close(fd);
}

main()
{
    char ch[1];
    int fd;

    mkfifo("np", 0666);

    signal(SIGINT, sigint);

    fd = open("np", O_RDONLY);

    read(fd, ch, 1);

    close(fd);

    printf("%c\n", ch[0]);
    return;
}

What I want is for main to block till something is written to the pipe. The problem is that the signal handler sigint() also blocks after opening the pipe. Is this supposed to happen given that the pipe is already opened for reading earlier in main() ?

+1  A: 

From the man page:

Opening a FIFO for reading normally blocks until some other process opens the same FIFO for writing, and vice versa.

and:

A process can open a FIFO in non-blocking mode. In this case, opening for read only will succeed even if no-one has opened on the write side yet; opening for write only will fail with ENXIO (no such device or address) unless the other end has already been opened.

Under Linux, opening a FIFO for read and write will succeed both in blocking and non-blocking mode. POSIX leaves this behaviour undefined. This can be used to open a FIFO for writing while there are no readers available. A process that uses both ends of the connection in order to communicate with itself should be very careful to avoid deadlocks.

+3  A: 

You're blocking in open() , opening a fifo for reading blocks until someone opens it for writing.

And opening a fifo for writing blocks until someone opens it for reading.

the signal handler runs in the same thread as your main(), so you'll get a deadlock. Neither will be able to open the fifo.

You can check what's going on by running your program under strace.

Anonym
This is on the right track - just expanding on the "runs in the same thread" part, the `SIGINT` causes the `open` for `O_RDONLY` to fail ("Interrupted System Call"), and *then* executes the signal handler (before the `open` call returns).
caf