Messages in this thread |  | | Date | Sat, 27 Jul 1996 13:51:51 +1200 (NZST) | From | Oliver Jowett <> | Subject | SO_SNDBUF makes select() hang |
| |
Hm, while playing with setting SO_SNDBUF through setsockopt() I noticed this behavior: if SO_SNDBUF is set low (I was trying 128) then select() won't ever show the socket as available for writing.
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++
|  |