New: backlog parameter of listen is not working with TCP
Subsystems (2)
A message that is not in the archive (sent off-list or not yet received): [email protected]/
(switched to email. Please respond via emailed reply-to-all, not via the bugzilla web interface).
Quoted 36 lines · On Wed, 1 Jul 2009 18:39:07 GMT [email protected] wrote:
http://bugzilla.kernel.org/show_bug.cgi?id=13688
Summary: backlog parameter of listen is not working with TCP
Product: Networking
Version: 2.5
Kernel Version: 2.6
Platform: All
OS/Version: Linux
Tree: Mainline
Status: NEW
Severity: normal
Priority: P1
Component: IPV4
AssignedTo: [email protected]
ReportedBy: [email protected]
Regression: NoCreated an attachment (id=22171)
--> (http://bugzilla.kernel.org/attachment.cgi?id=22171)
little test serverWhen creating a server I usually create a socket, bind it to any address and call listen to limit the queue size, then I call accept in a loop to handle clients one by one.
In a particular case I wanted to serve only 1 client and refuse the other connection attempts. I tried any value for the backlog parameter, whatever I use the server is not refusing any connection, though the queue should be full. The SYN+ACK handshake is completed everytime.
To be sure this is a bug I checked this with BSD and Windows, I can confirm that it refuses connections if the max queue size specified with backlog is reached (Note that backlog is not exactly the queue size with these systems, there is a 3/2 factor, I don't know why).
Quoted 8 lines
Maybe this implementation for linux kernel is wanted even if it is not posix compliant, but I did not find anywhere why this is working like this. If this is not a bug, could someone explain me the usefullness of the backlog parameter?
I attached a little test program with which anyone should be able to test this by connecting multiple telnet to.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/ip.h>
int main(void)
{
int servsock = 0;
int clientsock = 0;
struct sockaddr_in servaddr;
struct sockaddr_in clientaddr;
socklen_t clientaddrlen;
struct in_addr client_addr;
servsock = socket(AF_INET, SOCK_STREAM, 0);
//fcntl(servsock, F_SETFL, O_NONBLOCK);
if(servsock != -1)
{
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(6256);
inet_aton("0.0.0.0", &client_addr);
servaddr.sin_addr = client_addr; if(bind(servsock, &servaddr, sizeof(servaddr)) != -1)
{
if(listen(servsock, 0) != -1)
{
while(1)
{
printf("waiting for clients\n");
clientsock = accept(servsock, &clientaddr, &clientaddrlen);
if(clientsock != -1)
{
printf("client accepted, now sleep 60 sec\n");
sleep(60);
printf("60 sec have elapsed, closing connection\n");
close(clientsock);
}
else
{
printf("accept error: retrying in 1 sec...\n");
sleep(1);
}
}
}
else
{
printf("listen failed\n");
}
}
else
{
printf("bind failed\n");
} }
else
{
printf("socket creation failed\n");
} return 0;
}
Quoted 6 lines · Andrew Morton
Quoted 3 lines · On Wed, 1 Jul 2009 18:39:07 GMT [email protected] wrote:
http://bugzilla.kernel.org/show_bug.cgi?id=13688
Summary: backlog parameter of listen is not working with TCP
Product: Networking
[..]
Quoted 8 lines
Quoted 8 lines
When creating a server I usually create a socket, bind it to any address and call listen to limit the queue size, then I call accept in a loop to handle clients one by one.
In a particular case I wanted to serve only 1 client and refuse the other connection attempts. I tried any value for the backlog parameter, whatever I use the server is not refusing any connection, though the queue should be full. The SYN+ACK handshake is completed everytime.
The behaviour depends on net.ipv4.tcp_abort_on_overflow sysctl. If its on, new connections are reset once the backlog is exhausted.