On Suday the 11th of February, 2007 -after 3 and a half years on InvisionFree, we have moved! This old board remains as a read only archive of years past, and registration has been disabled here. All new and current members should register at http://www.cpplc.net/forum .


Please help out
Google

  Reply to this topicStart new topicStart Poll

> problem with zombies server/client, linux
icon0x
Posted: Jan 29 2007, 07:02 PM
Quote Post


KERNEL PANIC!


Group: Members
Posts: 87
Member No.: 1,662
Joined: 31-January 06



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;
  }
}



--------------------

user posted image

user posted image

user posted image


PMEmail Poster
Top
myork
Posted: Jan 30 2007, 03:36 PM
Quote Post


c++ guru


Group: Super Moderator
Posts: 2,584
Member No.: 487
Joined: 21-January 04



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.



PMEmail Poster
Top
« Next Oldest | C++ for Linux | Next Newest »


Topic Options Reply to this topicStart new topicStart Poll


Skin selector developed by XJONX. Skins created by various members of the IF Skin Zone and InvisionFree Skinning

Please help out
Hosted for free by InvisionFree (Terms of Use: Updated 7/7/05) | Powered by Invision Power Board v1.3 Final © 2003 IPS, Inc.
Page creation time: 0.0846 seconds | Archive