简体   繁体   中英

Non blocking read and blocking write on Posix PIPE

I'm writing Client-Server application using posix FIFO to communicate. Both client and server are single thread and single process application.

The server is design to handle multiple clients. Each client has own pair of named pipe, one to send messages from Server to this Client and the other to send messages from Client to the Server.

The idea is quite simple, Server loops through all Client to Server pipes and check if there is something to read there.

My first implemenentation was sth like:

/* SERVER */
int desc = open(pipeName, O_RDONLY | O_NDELAY); //1
assert(desc > 0); //just simplyfing error handling
int read = read(desc, buffer, BUFSIZE); //2
if(read > 0)
  do_stuff();
close(desc); //3

/* CLIENT */
int desc = open(pipeName, O_WRONLY) //4
assert(desc > 0); //just simplyfing error handling
int read = write(desc, buffer, BUFSIZE) //5
close(desc); //6

As far as I know this code is invalid.

There are race conditions and for example an order of calls like: 1, 2, 4, 3, 5, 6 - will probably cause SIGPIPE.

The problem is that nonblocking read open is always successful even if there is no writer on the other side of PIPE. That means that if Client will block on open() then server do nonblocking open (which will unlock Client) and then read() which will return 0 because at the moment nothing will be in PIPE and close() afterwards, then when control will go back to client which want to do write() on opened PIPE it will cause SIGPIPE as the reader is no longer available (server already closed the pipe).

For now i see two solutions:

  1. Handle SIGPIPE in Client with "tryAgain()" - this looks really bad, if i do such thing there is no guarantee that it will work at any moment - it will depend on possibility of good command processing order...
  2. Keep reading PIPE open all the time in Server (open it once and close when connection will be considered finished) - it is inconvenient in my application architecture but of course possible. I guess it will fix the problem but I'm not sure about that.

Here are my questions:

  1. Is any of those two approaches correct way to do that?
  2. Is there any other way to handle that scenario?
  3. Do you think second solution will work correctly?
  4. What would you choose and why?

Thanks for every answer.

I'm having a lot of trouble understanding your question. Things

Client will block on open() <== nothing blocks on open

Use select or epoll to determine which file descriptors are readable and writeable.

Then, just call read on those.

You will be notified that the client closed the pipe as a read event you'll need to handle and not write if it is closed.

http://linux.die.net/man/4/epoll

https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM