Suas hipóteses não estão corretas.
O comportamento esperado é que, uma vez que todos os escritores tenham fechado o fim de gravação do fifo que possuem, a extremidade de leitura fornece uma chamada única em read
que retorna 0 bytes. Você não deve chamar read
adicional depois: a extremidade de leitura deve ser fechada e aberta novamente para fazer isso, ou recriada se for um canal.
Se você seguir essa regra, terá um comportamento consistente em todas as plataformas.
Aqui está um exemplo de programa inspirado no seu que se comporta corretamente em ambas as plataformas:
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FILENAME "select_test_tmp.fifo"
int main()
{
pid_t pid;
int r_fd, w_fd;
unsigned char buffer[8192];
fd_set master_set, working_set;
char const * message = "Hello there\n";
mkfifo(FILENAME, S_IRWXU);
pid = fork();
if (pid < 0) exit(1);
if (pid == 0) {
w_fd = open(FILENAME, O_WRONLY);
if (w_fd == -1) exit(1);
write(w_fd, message, strlen(message));
close(w_fd);
exit(0);
}
r_fd = open(FILENAME, O_RDONLY);
if (r_fd < 0) exit(1);
FD_ZERO(&master_set);
FD_SET(r_fd, &master_set);
int finished = 0;
while (!finished) {
memcpy(&working_set, &master_set, sizeof(master_set));
int rc = select(r_fd + 1, &working_set, NULL, NULL, NULL);
if (rc < 1) exit(1); // No timeout so rc == 0 is also an error here
for (int fd = 0; fd < r_fd +1; ++fd) {
if (FD_ISSET(fd, &working_set)) {
if (fd == r_fd) { // Our fifo
// Read data and print it in stdout
ssize_t nb_bytes = read(r_fd, buffer, 8192);
if (nb_bytes < 0) {
exit(1);
}
else if (0 == nb_bytes) {
finished = 1;
}
else {
write(1,buffer,nb_bytes);
}
}
}
}
}
unlink(FILENAME);
exit(0);
}