I am trying to write 2 server/client programs under Linux, in which they communicate through named pipes. The problem is that sometimes when I try to write from the server into a pipe that doesn't exist anymore (the client has stopped), I get a "Resource temporarily unavailable" error and the server stops completely.
I understand that this is caused by using a O_NONBLOCK parameter when opening the fifo chanel, indicating the point where the program would usually wait until it could write again in the file, but is there a way to stop this behavior, and not halt the entire program if a problem occurs (shouldn't the write command return -1 ad the program continue normally)?
And another strange thing is that this error only occurs when running the programs outside the ide (eclipse). If I run both programs inside eclipse, on error the write function just returns -1 and the programs continues normally.
If you wish that write() to returns -1 on error (and set errno to EPIPE) instead of stopping your server completly when the write end of your pipe is unconnected, you must ignore the SIGPIPE signal with signal( SIGPIPE, SIG_IGN ).
The problem with this undefined behaviour is strange, you could have a memory problem somewhere or you missed a test. ( or Eclipse does something special to handle signals? )
To quote the section 2 man page for write:
"[errno=]EPIPE An attempt is made to write to a pipe or a FIFO that is not open for reading by any process, or that has only one end open (or to a file descriptor created by socket(3SOCKET), using type SOCK_STREAM that is no longer connected to a peer endpoint). A SIGPIPE signal will also be sent to the thread. The process dies unless special provisions were taken to catch or ignore the signal." [Emphasis mine].
As Platypus said you'll need to ignore the SIGPIPE signal:
signal(SIGPIPE, SIG_IGN). You could also catch the signal and handle the pipe disconnection in a different way in your server.
maybe you can just wrap it into a "try..catch" statement?
Related
I can receive and send data as long as I dont use fd_set(..) /select.
After that I can't send data to the client. The data is send "after" killing the process (pressing ctrl C).
For example if I run that snippet:
http://www.binarytides.com/multiple-socket-connections-fdset-select-linux/
I get the "welcome client-connected message" (line 126) but after the next loop, the new client is added via fd_set and select. Line 171 should send the received message back to the client, but I only get it back after killing the process.
Maybe it's because the "OS running the server" thinks that the connection is busy and buffers the output. And that could be the reason why killing the process causes the buffer to be send to client.
If I use write() instead of send() the behavoir doesn't change.
int count = write()
count is fine and the code doesn't throw any error.
I tried it on two ubuntu 14.04 systems (one lts and some other build from source)
If you need some more src-code I will upload it. I just think that the example in the link is well documented and shows the problem.
I already found a lot of stuff about the topic, but I can't figure out what I am doing wrong as all tutorials and docs do it that way.
Unluckily I am not that familiar with c++/linux and don't know what to investigate next. So any help is appreciated.
Thanks :)
My suspicion is that what you are seeing is not a network problem at all, but rather a buffering problem with your program's stdout stream. In particular, characters your program sends to stdout won't actually become visible in the terminal window until either (a) a newline character ('\n') is printed, or (b) you manually flush the stream (e.g. vi fflush(stdout), or cout.flush(), or (c) the program terminates (as happens when you press CTRL-C).
So most likely your client program did receive and print the message, but you aren't seeing it because the program is waiting for the newline character before printing anything to the terminal. (it makes sense to do that in cases where the program is printing out a line of text one small substring at a time; but it can be confusing)
The easy fix then (assuming this is indeed the problem), would be to call fflush(stdout) (or printf("\n"); after you call printf() to print the received text. (Or if you are using C++ streams, call cout.flush() or cout<<endl after your call to cout << theText)
Found the error, thanks Jeremy Friesner who mentioned the client. I read until "\n" occurs -> parse message. For testing my c++ server, I have sent messages without "\n". Thank you
I have a pipe (server) on one process waiting for clients with ConnectNamedPipe.
In the client process I'm waiting for the server to start listening with WaitNamedPipe, I gave it a timeout of 5000 ms.
I tried testing the client and even though the server wasn't running, WaitNamedPipe didn't wait at all.
I don't know if any code would be helpful here because I just try to use those methods. But if you want to see something, just tell me what is relevant. :)
oh, and the weird part is that it gave me error code 2: "file not found'.
Isn't it supposed to wait until the pipe is opened (the pipe is the "file", isn't it?)
What can cause WaitNamedPipe not wait?
It does not wait for a pipe to come into existence, it waits for an existing pipe to become available (i.e. an outstanding ConnectNamedPipe):
If no instances of the specified named pipe exist, the WaitNamedPipe
function returns immediately, regardless of the time-out value.
I have a program reading in from a file, doin some work on the input, then outputing it to a socket. It's been running fine for over a month when suddenly I started to get error 11 (EAGAIN?) error that kill the program. When I start 32 instances of the program more then half die within a few minutes receiving EAGAIN messages. I never set the file as non-blocking and besides which how would an input file block, the data is always there isn't it? The only change i made to this code was to disable the sigpipe signal to avoid the program dieing when it's socket connection is lost.
Forgive me for not posting code, but I can't copy and paste and the code is sort of spread out anyways. It's really as simple as opening a file on one line and calling readline(file, inputString) later on though.
Thanks.
EAGAIN means that the read has been interrupted by a signal and that it should be restarted.
I assume it is the SIGPIPE which used to directly kill your programs and now is handled (even if the handling is to do nothing).
I want to know whether its possible for tcp socket to report any broken pipe error immediately. Currently i am catching the sigpipe signal at the client side when server goes down ... but i found that the sigpipe signal is generated
only after 2nd msg is sent from client to server . what could be the possible reason for this?? If the other socket end went down , then the 1st send must return sigpipe .. y isnt that signal generated immediately..??
Is there any possible explanation to this peculiar behaviour?? And any possible way to get around this??
The TCP stack will only throw an error after some number of retransmission attempts. IIRC, the TCP retransmission timer is initialized to some small number of seconds and the number of retransmissions is typically 5-10. The protocol does not support any other means of detecting a peer that has become unreachable during a data exchange, (ie. someone tripped over the server power cable).
I think using SO_KEEPALIVE option may speed up broken link detection.
I want to know whether its possible for tcp socket to report any broken pipe error immediately
The other end of the pipe is across a network. That network could be slow and unreliable. So one end of the pipe can never instantly tell whether its partner still there. The delay could be quite long, so the O/S is also likely to do some bufferring. These considerations make it practically impossible to immediately detect a broken pipe.
And any possible way to get around this
But why would you want to? The pipe could be broken at any time during trans mission, so you have to handle the general case anyway.
I have a named pipe in my C++ program. A childprocess writes a value in it and the parent process reads it. I created the pipe by mkfifo and all operations are blocking (fifo cannot be opened for reading before it is tried to open for writing and v.v.
unfortunately sometimes my childprocess does not stop because of an error in a program the childprocess runs. It is not my task to fix this error in this external program but I want to make sure that the parent process does not stop for infinite time on the blocked open fifo call, but goes on after some time (without reading the value in the pipe).
So what I need it somethings like the WaitNamedPipe function. This function waits until either a time-out interval elapses or an instance of the specified named pipe is available for connection. http://ist.marshall.edu/ist480acp/namedpipes.html#WaitNamedPipe
Another way to realize this of course also works. I tried it with a loop in the parent process in which it always tries to open the pipe for reading and then sleeps if open is not possible.
That seems to have no effect, probably because the parent process is blocking on the first open call.
Thanks for any help.
You want O_NONBLOCK in your open(2) flags, see fifo(7). Then use select(2) or poll(2) to wait for input (with a timeout).
You can use a non-blocking pipe and select() call with a timeout. Or you can use a blocking read() call having called alarm() before it.