I am writing to a named pipe with a C program and reading it with a Python one.
If I stop the Python program (reader) then the writer just stops on its own although this is in a while(1) loop. Why does this happen? Is it a silent crash?
Second question what should I do if I wished to detect when the reader disconnects. My ideal scenario would be to detect the disconnection then go on idle (i.e. stop sending anything) and resume once the reader is back.
The toy codes below.
Writer (C):
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int fd;
// FIFO file path
char * myfifo = "/tmp/myfifo";
// Creating the named file(FIFO)
// mkfifo(<pathname>, <permission>)
mkfifo(myfifo, 0666);
char arr1[80];
while (1)
{
// Open FIFO for write only
fd = open(myfifo, O_WRONLY);
// Take an input from user.
fgets(arr1, 80, stdin);
// Write the input on FIFO
// and close it
write(fd, arr1, strlen(arr1)+1);
close(fd);
}
return 0;
}
Reader (Python)
f = open("/tmp/myfifo")
while 1:
print(f.readline(), end = "")
f.close()
When you stop the reading program, the writer will receive a SIGPIPE
signal when it tries to write to the pipe. The default disposition of this signal is to terminate the process.
If you want to detect this condition, use signal()
or sigaction()
to change the disposition to SIG_IGN
. Then writing to the pipe will report the EPIPE
error.
Also, you shouldn't close and reopen the pipe each time through the loop. Open it once at the beginning, and close it at the end. Closing the pipe causes the reader to get EOF, and it won't be able to read anything after that.
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
int main()
{
int fd;
// FIFO file path
char * myfifo = "/tmp/myfifo";
// Creating the named file(FIFO)
// mkfifo(<pathname>, <permission>)
mkfifo(myfifo, 0666);
// Open FIFO for write only
fd = open(myfifo, O_WRONLY);
signal(SIGPIPE, SIG_IGN);
char arr1[80];
while (1)
{
// Take an input from user.
fgets(arr1, 80, stdin);
// Write the input on FIFO
// and close it
int res = write(fd, arr1, strlen(arr1)+1);
if (res < 0) {
perror("write");
break;
}
}
close(fd);
return 0;
}
When you stop the writing program, the reader will get EOF when it tries to read from the pipe. When f.readline()
gets to EOF, it returns an empty string. Your Python script doesn't check for this, so it loops infinitely.
Change the reader to:
with open("/tmp/myfifo") as f:
while True:
line = f.readline()
if not line:
break
print(line, end = "")
Then the loop will terminate when the pipe is closed.