question about using freebsd threads

liupeng liu_peng at ec.com.cn
Fri May 11 11:28:13 UTC 2007


Hi,
  I've a problem with using threads.
  I write a simple proxy server on freebsd like this:

========================================================================================================
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>

int scListen=-1;
int igConnNum=5;

#define BUF_LEN_4K 4096

int Sys_recv(char* pBuf, int iBufLen, int scCon )
{

 int iResult = 0;

 iResult = recv(scCon, pBuf, iBufLen, 0);

 return iResult;

}

int Sys_send(char* pBuf, int iBufLen, int scCon )
{

 int iResult=0;

  for (int iWrite = 0; iWrite < iBufLen; iWrite += iResult)
  {
   iResult = send(scCon, pBuf + iWrite, iBufLen - iWrite, 0);
   if (iResult <= 0)
    return iResult;
  }


 return iResult;

}


int Sys_Connect( const char* szAddr, unsigned int uiPort)
{
 int scCon = -1;
 struct sockaddr_in addr;
 
 int nRv = 0;
 
 int nerr=0;
 int ndata=1;


 scCon = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 

 if (scCon == -1)
 {
  return scCon;
 }

 if(szAddr)
 {  
  addr.sin_addr.s_addr = inet_addr(szAddr);
 }


 addr.sin_family = AF_INET;
 addr.sin_port = htons((short)uiPort);

 if (connect(scCon, (struct sockaddr *)&addr,sizeof(addr)) == -1)
 {
  close(scCon);
  scCon = -1;
 }

 return scCon;

}

void * internalThreadProc(void* lpParam)
{
 int scCon;
 int scServer=-1;
 int iCount=0;
 char *pBuffer=NULL;
 int iRet=0;
 fd_set fdRecv;
 struct timeval timeout;
 
 scCon=*((int *)lpParam);
 free(lpParam);
 
 printf("thread %d created\n",pthread_self());
 
 pthread_detach(pthread_self());
 
 scServer = Sys_Connect( "211.88.5.12", 80);
 if( scServer == -1 )
 {
  goto End;
 }
 
 pBuffer         = new char[BUF_LEN_4K+1024];
 if(pBuffer == NULL) 
 {
  printf("alloc memory failed\n");
  goto End;
 }

 timeout.tv_sec  = 300;
 timeout.tv_usec = 0;



 int max;    
 max = (scCon > scServer) ? scCon : scServer;
  
 while(1)
 {
  
  FD_ZERO(&fdRecv);
  FD_SET(scCon, &fdRecv);
  FD_SET(scServer, &fdRecv);
  
  iRet=select(max+1, &fdRecv, NULL, NULL, &timeout);
  
  if ( iRet > 0 )
  {
   if(FD_ISSET(scCon,&fdRecv))
   {
    
    memset(pBuffer,0,BUF_LEN_4K);
    iCount = Sys_recv(pBuffer, BUF_LEN_4K, scCon );
    if (iCount>0)
    {
     iCount = Sys_send( pBuffer, iCount, scServer );
     if (iCount>0)
     {
      continue;
     }
     else
     {
      goto End;
     }
    }
    else
    {
     goto End;
    }
   }
   else if(FD_ISSET(scServer,&fdRecv))
   {
    memset(pBuffer,0,BUF_LEN_4K);
    iCount = Sys_recv( pBuffer, BUF_LEN_4K, scServer );
    if (iCount>0)
    {
 
     iCount = Sys_send(pBuffer, iCount, scCon );
     if(iCount <= 0)
     {
 
       goto End;
     }
     
    
    }
    else
    {
     goto End;
    }
   }
   else
   {
    goto End;
   }
  }
  else
  {
   //printf("select < 0 ,err=%d\n",errno);
   
  }
 }
  


End: 
 if (scServer!=-1)
  close(scServer);
 if (scCon!=-1)
  close(scCon);
 if(pBuffer)
  delete[] pBuffer;
  
 printf("thread %d terminated\n",pthread_self());
 
 return NULL;

}

int Sys_CreateListenPort( unsigned int uiPort, bool bTCP, char *sIP )
{
 struct sockaddr_in addr;
 int scListen = -1;

 if( bTCP )
  scListen = socket(AF_INET, SOCK_STREAM, NULL);
 else
  scListen = socket(AF_INET, SOCK_DGRAM, NULL);


 if( sIP != NULL )
  addr.sin_addr.s_addr =  inet_addr((const char*)sIP);
 else
  addr.sin_addr.s_addr =  htonl(INADDR_ANY);

 addr.sin_family = AF_INET;
 addr.sin_port = htons((short)uiPort);

 if (bind(scListen, (struct sockaddr*)&addr, sizeof(struct sockaddr)))
 {
  close(scListen);
  scListen = -1;
  return scListen;
 }

 if( bTCP )
 {  
  if (listen(scListen, igConnNum))
  {
   close(scListen);
   scListen = -1;
   return scListen;
  }
 }

 return scListen;
}


void *CreateThreadForRequest(void *pPARAM)
{
 pthread_t mythread;
  
 int *scClient=NULL;
 
 
 while(1)
 {
   scClient=(int *)malloc(sizeof(int));
   
   *scClient=accept(scListen,NULL,0);
   
   if (*scClient<0)
   {
    printf("accept failed\n");
    continue;
   }

   if (!pthread_create(&mythread,NULL,internalThreadProc,(void *)scClient))
   {
   }
   else
   {
     printf("create thread internalThreadProc failed\n"); 
   }
  
 }
 
}


int main(int argc,char *argv[])
{
 pthread_t uiThreadID;
 int nData=1;
 linger l_tmv;
      
 
 signal(SIGPIPE,   SIG_IGN);   
 
 scListen=Sys_CreateListenPort(443,1,"211.88.8.182");
 if (scListen==-1)
 {
  printf("error in create listen socket\n");
  goto cleanup;
 }
 
 if(pthread_create(&uiThreadID,NULL,CreateThreadForRequest,NULL))
 {
  printf("create thread CreateThreadForRequest fail!!!!\n");
  return false;
 }
 
 
 if (pthread_join(uiThreadID,NULL))
  {
   printf("pthread join failed\n");
   return false;
  }
 
 

cleanup:
 return 0; 
 
}
========================================================================================================

Freebsd platform:
FreeBSD Jail-161 6.2-RELEASE FreeBSD 6.2-RELEASE #0: Fri Jan 12 11:05:30 UTC 2007     root at dessler.cse.buffalo.edu:/usr/obj/usr/src/sys/SMP  i386

Compiler gcc:
gcc (GCC) 3.4.6 [FreeBSD] 20060305
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Compile option:
g++  -g  -o test test.cpp -lpthread

I use loadrunner to test my proxy server,it crashed at about 500 vuser.

the coredump information:
(gdb) where
#0  0x28098537 in pthread_testcancel () from /lib/libpthread.so.2
#1  0x28090ec8 in pthread_mutexattr_init () from /lib/libpthread.so.2
#2  0x2807a450 in ?? ()

I try to change my compile option use -pthread or -lc_r,but it still crashed,why? Does someone can give suggestions?


  


More information about the freebsd-threads mailing list