Possible problem with ACCEPT/CONNECT in

From: Peter Zaitsev (pz@spylog.ru)
Date: Fri Apr 07 2000 - 03:38:26 EST


Resently I wrote to this list about problem with strange slowdown on network
connections. Now I have done some investigations and must say the problem
really exists and repeatable !. Both 2.2 and 2.3 kernels are atthected in
SMP and non-SMP configuration.
The problem is then many clients are trying to connect the same port, they
sometimes get locked for a long time even then CPU usage on server is low
and it is able to do needed number of accepts in a time.
The problem persists the client and server are on the same or on different
machines, and even then number of server processes doing accept() is grater
then the number of clients running.
The next strange the times taken by connect() - if it does not pass
momentaly it gots locked for 3 9 21 45 ... seconds.

I can't get this problem 100% repeatable. The funny thing is on the same and
same loaded machine sometimes I got the problem with the same program and
sometimes I do not, so the only way I was able to repeat it is to play with
parameters a bit (number of listening and connecting process).
The other interesting effect I got is getting error #11 then not expected
to - then for example number of listening processes is 10 each haveing back
buffer at least 5 and 11-12 processes are connecting - some of them are
getting an error...

I attach the scripts I used to reproduce this problem. Or please tell me if
this is an expected behavior.
As server script I tryed to use not only hand written program but others -
for example APACHE - the problem persist.

----------------------------------------------------------------------------
--------------------------
client
----------
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <strings.h>
#include <unistd.h>

#define CONNECTS 10000
#define PROCESSES 200
#define LONG_CONNECT 2
#define HOST "localhost"
#define PORT 3333

main()
 {
  int sock;
  int t,i;
  int res;
  int c;
  int tm;
  int total;
  struct sockaddr_in serv_addr;
  struct hostent *hp;
  for(t=0;t<PROCESSES;t++)
   if (fork()==0)
    {
     // Here we have the process forked.
     hp=gethostbyname(HOST);
     if (hp==NULL) printf("Lookup failed !");
     total=time(NULL);
     for(c=0;c<CONNECTS;c++)
     {
      tm=time(NULL);
      i=socket(PF_INET,SOCK_STREAM,0);
      if (i==-1) printf("Can't create socket: %d\n",errno);
      bzero(&serv_addr,sizeof(serv_addr));
      bcopy(hp->h_addr,&serv_addr.sin_addr, hp->h_length);
      serv_addr.sin_family=hp->h_addrtype;
      serv_addr.sin_port=htons(PORT);
      res=connect(i,&serv_addr,sizeof(serv_addr));
      if (res==-1)

                     printf("Error while connecting: %d\n",errno);
                     return 0;
                   }
      close(i);
      tm=time(NULL)-tm;
      if (tm>LONG_CONNECT) // two seconds FRESHHOLD
         printf("Long connect time: %d\n",tm);
      }
      total=time(NULL)-total;
      printf("Total time spent for connecting: %d\n",total);
     return 0;
    }
 }

--------------------------------- Server--------------------------------
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <netdb.h>
#include <sys/un.h>
#include <unistd.h>
#define PROCESSES 20

int main(){
    struct sockaddr_in serv_addr,clnt_addr;
    int sockfd,sockfd1;
    int n,nport=3333;
    int opt = 1;
    int i;
    socklen_t caddrlen;
    nport=htons((u_short)nport);
    sockfd=socket(AF_INET,SOCK_STREAM,0);
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    opt=1;
    setsockopt(sockfd,SOL_TCP,TCP_NODELAY,&opt,sizeof(opt));
    bzero(&serv_addr,sizeof(serv_addr));
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_addr.s_addr=INADDR_ANY;
    serv_addr.sin_port=nport;
    while(bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0){
     printf("error bind\n"); sleep(5);
      }
    if(listen(sockfd,100)<0)printf("error listen\n");
    for(i=0;i<PROCESSES;i++)
     if (fork()==0)
     for(;;){
       bzero(&clnt_addr,sizeof(clnt_addr));
       caddrlen=sizeof(clnt_addr);
       sockfd1=accept(sockfd,(struct sockaddr*)&clnt_addr,&caddrlen);
       if(sockfd1<0) continue;
       close(sockfd1);
      }
}

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Apr 07 2000 - 21:00:18 EST