I am creating three FIFO pipes for a single process where multiple writer threads write to a single reader thread. The goal is a separate file descriptor for each writer thread with a corresponding reader file descriptor for each writer file descriptor so that I know which writer thread belongs to each record. My setup works fine with one writer file descriptor shared among all writer threads and a single reader file descriptor.
The multiple reader/writer setup works successfully to set up three writer fds (6, 7, 8) and three reader fds (9, 10 and 11). All writer threads successfully send data, BUT the reader fds do not successfully read the data (return zero bytes read).
When I open the fd on the writer side, I get the error message "open: Bad file descriptor" but it still returns a unique fd, and that fd is used successfully to write, but not to read.
I call the C programs from NASM in a loop, one iteration for each writer thread:
xor r12,r12
mov r13,[Number_Of_Cores_Calc]
Setup_pipe:
lea rdi,[fifo_base_name]
mov rax,r12
add rax,48
mov byte[rdi+11],al
call fifo_delete wrt ..plt
call fifo_setup wrt ..plt
push rdi
call fifo_close wrt ..plt
pop rdi
Open_FIFO_Write:
mov rsi,1
call fifo_open wrt ..plt
lea rbp,[fifo_write_fds]
mov [rbp+r12*8],rax
add r12,1
cmp r12,r13
jl Setup_pipe
The corresponding C programs:
int64_t fifo_setup(char * fifo_name)
{
remove(fifo_name);
if (mkfifo(fifo_name, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH) == -1) {
perror("mkfifo");
exit(EXIT_FAILURE); }
return 0;
}
int64_t fifo_open(char * fifo_name, int64_t read_write) {
int c;
if (read_write == 1) {
c = open(fifo_name, O_CREAT | O_RDWR);} //O_WRONLY
if (read_write == 2) {
c = open(fifo_name, O_CREAT | O_RDWR);} //O_RDONLY
perror("open");
return (c);
}
int64_t fifo_read(int fd, void *buf, size_t count) {
int status_read = read(fd, buf, count);
return status_read;
}
int64_t fifo_write(int fd, const void *buf, size_t count) {
int status_write = write(fd, buf, count);
return status_write; }
int64_t fifo_close(int fifo_fdes) {
close(fifo_fdes);
return 0; }
// Delete pre-existing file
int64_t fifo_delete(char * fifo_name) {
if( access( fifo_name, F_OK ) != -1 ) {
if (remove(fifo_name) == 0)
printf("File deleted successfully");
else
printf("Unable to delete the file");
}
return 0; }
So my questions are:
Can I write from multiple threads to a single reader thread using separate fds for each thread on both the write and read sides?
If I can, what did I do wrong above -- especially why am I getting "open: Bad file descriptor" but I still get what looks like a valid file descriptor.
If I can't use POSIX FIFOs, what IPC methods can I use so each writer thread has its own unique fd on both writer and reader sides? Datagram sockets?
Thanks for any help on this.
open(2)cannot returnEBADF, onlyopenat(2). And ifcis a positive number, then what you're seeing is a previous value oferrnoor something. - bnaeckeraccess()! This is intended for specialized setuid/setgid applications to find out if the underlying user would be able to access the file, it's absolutely not a handy-dandy "does the file exist?" function. Usestat()instead to check for existence. - Steve Friedlperror()unconditionally; only call it if the return value indicates an error. Similarly witherrno; don't test it unless the function called indicates an error. - Jonathan LefflerO_CREATflag doesn't seem to make sense. With it, if the fifo you're trying to open doesn't exist, you'll create a regular file with the same name instead. And moreover since you don't pass a third argument toopen(), that file will get random permissions. - Nate Eldredge