Avoiding "broken pipe" errors with a socket server.

I recently found out that having a certain php script connect to my server makes it crash due to a broken pipe error. As I understand, these are caused by writing to a closed socket. Is there a way I can check a socket's integrity before making the send statement? Or is there any other way to keep the broken pipe from shutting down the whole program?
I found this code the other day for exactly that task.

However I have not tried to compile or run this yet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <poll.h>          // For poll()

bool is_client_closed(int cs)
{
	pollfd pfd;
	pfd.fd = cs;
	pfd.events = POLLIN | POLLHUP | POLLRDNORM;
	pfd.revents = 0;
	while(pfd.revents == 0)
	{
		// call poll with a timeout of 100 ms
		if(poll(&pfd, 1, 100) > 0)
		{
			// if result > 0, this means that there is either data available on the
			// socket, or the socket has been closed
			char buffer[32];
			if(recv(cs, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0)
			{
				// if recv returns zero, that means the connection has been closed:
				return true;
			}
		}
	}
	return false;
}


Let me know if it works ;-)
Last edited on
Oh and the parameter cs above is the client socket.
Ok, so I only write to a socket if that function returns false? I'll try it out, thanks.
Last edited on
Yes, that seems right :)

1
2
3
4
5
6
7
8
if(is_client_closed(client_socket))
{
	throw client_closed_exception;
}
else
{
	// write to socket...
}

Last edited on
Alright, it seems to solve the broken pipe error, but it seems like it causes other problems, such as not giving the message it's supposed to when the user first connects. I'll have to see what I can do to work around it. Thanks for your help.

EDIT: It's possible that the function's not the cause. I'll report back later after more experimentation.
Last edited on
Ok, from what I can tell calling that function is what's causing my problems, but not because of false positives. Is it possible that the recv call is eating input despite the MSG_PEEK?
It works if I take out all the polling stuff and just use this
1
2
3
4
5
6
char buffer[32];
			if(recv(cs, buffer, sizeof(buffer), MSG_PEEK) == 0) //the socket's already nonblocking, so I took out the "don't wait"
			{
				// if recv returns zero, that means the connection has been closed:
				return true;
			}
Thanks again for your help.
Oh cool. That may well help me when I come to use this!
I would think that send() would return -1 with errno=ENOTCONN.

You need to handle SIGPIPE. That is what is causing the program to abort.
You should be able to ignore the signal, then recv() would return -1 with
errno=EPIPE I think (OTOMH).
Oh, ok, thanks. How do I handle it?
Look up sigaction() in the man pages. It will give you examples of how to register
signal handlers / ignore signals.
I'll do that when I get the chance, thanks again.
Topic archived. No new replies allowed.