Consider the following EXAMPLE code:
#include <sys/socket.h>
int main()
{
int sv[ 2 ] = { 0 };
socketpair( AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, sv );
for( unsigned ii = 0; ii < 5; ++ii )
{
int* msg = new int( 123 );
if( -1 == send( sv[ 0 ], &msg, sizeof(int*), MSG_NOSIGNAL ) )
{
delete msg;
}
}
close( sv[0] );
sleep( 1 );
int* msg = 0;
int r;
while( ( r = read( sv[ 1 ], &msg, sizeof(int*) ) ) > 0 )
{
delete msg;
}
return 0;
}
Obviously, the code works fine, but it doesn't mean it's not UB.
Couldn't find anything in the man pages, which guarantees, that when sv[ 0 ]
is closed, the read
will still be able to read everything from sv[ 1 ]
, sent by the send
.
Maybe the question could be asked like this - as read
returns 0
for EOF
and as the socketpair
is SOCK_STREAM
, I expect the EOF
will be "hit" once everything is read from the socket and the other side is closed. Is this correct?
AFAIK it can work, but smells UB.
The correct way is the graceful shutdown :
shutdown(s, 1)
or (better shutdown(s, SHUT_WR)
)
- read until eof on input
- only then call close.
(References : http://msdn.microsoft.com/en-us/library/windows/desktop/ms738547%28v=vs.85%29.aspx, Graceful Shutdown Server Socket in Linux)
Edit :
After reading R.. comment, I wondered if I was not a little confused, did some tests and read documentation again. And ... I now think what I said is true for general socket usage (include AF_INET sockets), but not for the special AF_INET socketpair.
My test was put a little more stress on the system, since I send 8 packets of 1024 bytes on a FreeBSD 9 system. I stopped there because sending more would have blocked. And after the close on sv[0] I could successfully read my 8 packets.
So it works on different kernels, but could not find a valid reference for it except that AF_UNIX sockets do not support OOB data.
I could also confirm that using shutdown, works fine.
Conclusion :
As far as I am concerned, I would stick to graceful shutdown for closing a socket, but mostly because I do not want to think about the underlying protocol.
Hope somebody else with more knowledge could give a piece of reference documentation