This bit of code demonstrates the problem:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void main(void)
{
int s;
struct sockaddr_in addr;
int v;
fd_set writefds;
s=socket(AF_INET, SOCK_STREAM, 0);
addr.sin_family=AF_INET;
addr.sin_port=htons(9); /* discard */
addr.sin_addr.s_addr=inet_addr("127.0.0.1");
connect(s, (struct sockaddr *)&addr, sizeof(addr));
v=128;
printf("SO_SNDBUF: %d\n",
setsockopt(s, SOL_SOCKET, SO_SNDBUF, &v, sizeof(v)));
printf("write: %d\n",
write(s, &v, sizeof(v))); /* this works */
FD_ZERO(&writefds);
FD_SET(s, &writefds);
printf("select: %d\n",
select(FD_SETSIZE, NULL, &writefds, NULL, NULL)); /* this blocks?! */
close(s);
exit(0);
}
The write succeeds, but the select blocks indefinitely.
I'm not very familiar with the network code, but I think this is due to
this check in tcp_select (net/ipv4/tcp.c):
if (sock_wspace(sk) < sk->mtu+128+sk->prot->max_header)
break;
return 1;
sock_wspace returns sk->sndbuf - sk->wmem_alloc normally, so if sk->sndbuf
is too small then the socket will never become available for writing in
tcp_select.
The SO_SNDBUF code (net/core/sock.c) checks for a buffer size < 256 and
resets it to 256, but it would appear that 256 is always less than
sk->mtu+128+sk->prot->max_header. Should the SO_SNDBUF code check for this
minimum size instead?
[this is with 2.0.0, but I didn't see any changes to this bit of the code in
the .1-.9 patches]
Oliver
-- "C makes it easy to shoot yourself in the foot. C++ makes it harder, but when you do, it blows away your whole leg."-- Bjarne Stroustrup on C++