View Full Version: problem with zombies server/client

C++ Learning Community > C++ for Linux > problem with zombies server/client


Title: problem with zombies server/client
Description: linux


icon0x - January 29, 2007 07:02 PM (GMT)
issue, when closing the client, the server leaves behind zombies, shouldnt waitpid take care of this problem?


//server
CODE


#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <wait.h>

#define MAXLINE 2048

void sig_child( int signo );
void str_ser( int* );

int main( int argc, char** argv ){

  pid_t childpid;
  int listenfd,clientfd,n;
  socklen_t len;
  sockaddr_in servaddr,clientaddr;

  if( (listenfd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )) < 0){
     std::cout<<"socket error"<<std::endl;
     exit( -1 );
  }

  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons( 9090 );
  servaddr.sin_addr.s_addr = htonl( INADDR_ANY );

  if( bind( listenfd, (sockaddr*)&servaddr, sizeof( servaddr )) < 0 ){
     std::cout<<"bind error"<<std::endl;
     exit( -1 );
  }

  listen( listenfd, 12);

  signal(SIGCHLD, &sig_child );

  while( true ) {
     len = sizeof( clientaddr );
     if( ( clientfd = accept( listenfd, (sockaddr*)&clientaddr, &len)) < 0){
        if( errno == EINTR )
           continue;
        else
           std::cout<<"accept error!"<<std::endl;
     }

     if( (childpid = fork()) == 0){
        close( listenfd );
        str_ser( &clientfd );
        exit(0);
     }
     
     close( clientfd );

  }
std::cout<<"EXITING SERVER!"<<std::endl;
}

void sig_child( int signo ){
  int stat;
  pid_t pid;
  while( (pid = waitpid(-1, &stat, WNOHANG )) > 0){
     printf(" child %d terminated\n", pid );
  return;
  }
}

void str_ser( int* sock ){
  int n;
  char readline[ MAXLINE ];
   while((n = read( *sock, readline, MAXLINE)) > 0){
     readline[n] = 0;
     std::cout<<readline<<std::endl;
  }
}



//client

CODE



#include <iostream>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <wait.h>

#define MAXLINE 2048

void str_cli( int* sock );

int main( int argc, char** argv ){

  pid_t childpid;
  int connfd[5],n;
  sockaddr_in servaddr;

  if( argc != 3){
     std::cout<<"Usage: ./client <IP address> <port>"<<std::endl;
     exit( -1 );
  }

  for(int i = 0; i < 5; i++ ){
     if( (connfd[i] = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )) < 0 ){
        std::cout<<"socket error: "<<i<<std::endl;
        exit( -1 );
     }
  }

  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons( atoi(argv[2]) );
  if( inet_pton( AF_INET, argv[1], &servaddr.sin_addr ) <= 0 ){
     std::cout<<"inet_pton error"<<std::endl;
     exit( -1 );
  }

  for( int i = 0; i < 5; i++ ){
     if( connect( connfd[i],(sockaddr*)&servaddr,sizeof( servaddr )) < 0 ){
        std::cout<<"connect error: "<<i<<std::endl;
        exit( -1 );
     }
  }
 

  str_cli( &(connfd[0]) );

}

void str_cli( int* sock )
{
  char sendline[ MAXLINE ];
  int n;
  strcpy( sendline, "echo");
  write( *sock, sendline, 4);

   while((n = read( *sock, sendline, MAXLINE)) > 0){
     sendline[n] = 0;
     std::cout<<sendline<<std::endl;
  }
}


myork - January 30, 2007 03:36 PM (GMT)
QUOTE (icon0x @ Jan 29 2007, 02:02 PM)
CODE

     if( (childpid = fork()) == 0){
        close( listenfd );
        str_ser( &clientfd );
        exit(0);
     }




There is no point doing a 'waitpid()' inside the signal handler as the process is already dead. Use this if you want the parent to suspend and wait for a child to die.

It is probably not a good idea to use 'waitpid()' inside a signal handler (but read documentation about that).

Since the 'waitpid()' is in a signal handler it will not get executed in the normal flow of the code.



Each child process is sitting inside a loop
CODE
while((n = read( *sock, readline, MAXLINE)) > 0)
This condition will only be false when the socket is closed. This will happen when the client dies or explicitly coses the connection (assuming it was all set up correctly with no errors).

The client on the other hand is sitting inside a loop
CODE
while((n = read( *sock, sendline, MAXLINE)) > 0)
so he will never die (unless the attached child closes the socket [which it will not]).


So both processes are stuck waiting for each other.







Hosted for free by InvisionFree