question about using freebsd threads
lpbpu at 126.com
lpbpu at 126.com
Fri May 11 11:52:55 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