I am trying to send data from javascript to C via a named pipe/FIFO. Everything seems to be working other than every couple messages there will be an additional iteration of the loop reading 0
bytes rather than the expected 256
. I realize I could add something like if (bytes_read>0) {...
but this seems like a band aid to a bigger problem.
From my testing it looks like the open()
call in the reader
is unblocked when the writer
opens AND closes the file. It looks like sometimes the reader
is ready (and blocked on open) for the next message before the writer
closes the file from the previous so it will run through its loop twice per message.
Is this just expected behavior or am I misunderstanding something? Any advice would be greatly appriciated!
Writer:
uint32_t writer(buf)
{
int fd;
// FIFO file path
char * myfifo = "/tmp/channel";
// Creating the named file(FIFO)
// mkfifo(<pathname>, <permission>)
mkfifo(myfifo, 0666);
// Open FIFO for write only
fd = open(myfifo, O_WRONLY);
uint32_t written = write(fd, buf, sizeof(char)*256);
close(fd);
return written;
}
Reader:
int main()
{
int fd;
// FIFO file path
char * myfifo = "/tmp/channel";
// Creating the named file(FIFO)
mkfifo(myfifo, 0666);
while (1)
{
char buf[256] = "\0";
// Open FIFO for Read only
fd = open(myfifo, O_RDONLY);
// Read from FIFO
int bytes_read = read(fd, buf, sizeof(char)*256);
struct access_point *dev = (struct access_point *) &buf;
printf("Bytes read: %i\n", bytes_read);
printf("ssid: %s\n", dev->ssid);
int r = close(fd);
//sleep(0.01);
}
return 0;
}
After 5 calls to writer the output will look like:
# Call 1 (bad)
Bytes read: 256
ssid: kremer
Bytes read: 0
ssid:
# Call 2
Bytes read: 256
ssid: kremer
# Call 3
Bytes read: 256
ssid: kremer
# Call 4 (bad)
Bytes read: 256
ssid: kremer
Bytes read: 0
ssid:
# Call 5
Bytes read: 256
ssid: kremer
A read
or 0 bytes indicates the pipe was closed on the other end. So this is absolutely expected behavior.
So you do have to catch that 0 and read again so the kernel waits for the next time the pipe is opened.
Note: read
can also return -1
with errno set to EINTR
. Same deal, just read again.