I have two processes A and B. The communication flow is always A -> B, but I need to do it using a named pipe, because I must use the pipe file descriptor in a select call inside the B process, and the data written to the pipe must persist when any or both of the processes exit.
The pipe is opened in non-blocking mode on both ends. In process A:
int push_fifo_fd = open(FIFO_NAME, O_WRONLY | O_NONBLOCK | O_CREAT, 0644);
In process B:
int fd = open(FIFO_NAME, O_RDONLY | O_NONBLOCK | O_CREAT, 0644);
Q1. The process B uses curl multi interface, so I get the fd_sets of the curl multi handle and add the "fd" descriptor to the read fd_set, than make a call to select, to get the file descriptors available for reads and writes. In every call to select, "fd" is contained in the result read fd_set, but read returns 0, even if the write end is opened. This causes the process B to use 100% of processor time. I mention that I don't know to order in which the ends of the pipe are opened. The relevant code from B:
while (1)
{
fd_set read_fds, write_fds, err_fds;
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
FD_ZERO(&err_fds);
FD_SET(fifo_fd, &read_fds);
// some code
ccode = curl_multi_fdset(curlm, &read_fds, &write_fds, &err_fds, &max_fd);
max_fd = MAX(max_fd, fifo_fd);
rc = select(max_fd + 1, &read_fds, &write_fds, &err_fds, &timeout);
switch (rc)
{
case -1:
WARN("select");
continue;
case 0:
default:
{
if (FD_ISSET(fifo_fd, &read_fds))
{
// read from the fifo_fd
}
/* Now look at the handles that need attention */
int old_running_handles = running_handles;
ccode = curl_multi_perform(curlm, &running_handles);
if (ccode != CURLM_OK && ccode != CURLM_CALL_MULTI_PERFORM)
{
WARN("curl_multi_perform error: %s", curl_multi_strerror(ccode));
continue;
}
if (running_handles != old_running_handles)
{
CURLMsg *curl_msg;
int left_msgs = 0;
while ((curl_msg = curl_multi_info_read(curlm, &left_msgs)) != NULL)
{
// treat each easy handle
}
}
}
break;
}
}
Q2. In "man 7 fifo" is said "A process can open a FIFO in nonblocking 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." but the process A always can open successfully the write end of the pipe in non-blocking mode even the read end is not opened. Why is that? The platform on which I test is Ubuntu server 12.04.3, kernel 3.8.0-29.
A process can open a FIFO in nonblocking mode. In this case, opening for read-only succeeds even if no one has opened on the write side yet and opening for write-only fails with ENXIO (no such device or address) unless the other end has already been opened.
FIFO (fly-in fly-out) is a popular working arrangement in the mining, construction, oil and gas industries. FIFO employees fly in to their work site for the duration of their roster, before flying home.
The Q1 is expected by select()
or poll()
. See the linked question. A graceful resolution is to open another fd on the same fifo and close the original.
I believe the Q2 was also expected on some versions of kernel. The man 7 fifo have a paragraph about it:
Under Linux, opening a FIFO for read and write will succeed both in
blocking and nonblocking mode. POSIX leaves this behavior undefined.
This can be used to open a FIFO for writing while there are no
readers available.
That paragraph seems to claim that you can successfully open the write end of a fifo anytime, as observed in Q2 by the original author.
Though it seems to contradict the previous paragraph as the original question quoted also from the man 7 fifo page that is basically saying the open shall fail instead of succeed:
A process can open a FIFO in nonblocking mode. In this case, opening
for read-only succeeds even if no one has opened on the write side
yet and opening for write-only fails with ENXIO (no such device or
address) unless the other end has already been opened.
I'm seeing opening the write end in non-blocking mode shall fail when the read end is not open, on a 4.9.37 kernel. It must have changed from version 3.8 to 4.9, I guess.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With