Thread: Select handling more then 500 connections

  1. #1
    Registered User
    Join Date
    Jul 2002
    Posts
    47

    Select handling more then 500 connections

    Select is giving me trouble when I have more then 500 connections.
    My errorhandler is telling me the system seg faults when it tries to use the FD_SET command once I get over 500 or so connections. This mainly happens when my program is accepting connections. Once someone is already connected it does not seem to have a problem in this area, but new connections can cause the segmentation fault. if anyone knows why this is doing this please let me know.

    Here is the code for my Socket_Core

    Code:
    void cSCore::runcore(void)
    {
    	/*Lets Initialize Some Variables*/
    	int *lsfd = new int; //Listening File Descriptor
    	int *nsfd = new int; //Sfd For New Connections
    	int returnval;
    	int *maxfd = new int;
    	char *buffer; //Temporary Message Buffer
    	char *charbuffer = new char[1];
    	struct sockaddr_in *newc = new sockaddr_in;
    	fd_set *cset = new fd_set;
    	fd_set *master = new fd_set;
    	memset(charbuffer,0,1);
    	*lsfd = Socket->cs_serve(Port);
    	int *optval = new int;
    	*optval = 1;
    	setsockopt(*lsfd,SOL_SOCKET,SO_REUSEADDR,optval,sizeof(*optval));
    	//FD_ZERO(cset);
    	FD_ZERO(master);
    	FD_ZERO(cset);
    	FD_SET(*lsfd, master); //Add the listening sfd to the FD set
    	*maxfd = *lsfd;
    	sMainUsers *tempuser;
    	while(enabled)
    	{
    
    		*cset = *master;	
    		select((*maxfd)+1,cset,NULL,NULL,NULL);
    		if(FD_ISSET(*lsfd, cset)) //If It is a New Connection
    		{
    			*nsfd = accept(*lsfd,NULL,(socklen_t *)sizeof(*newc));
    			ErrorHandler->ProduceError(0,"cSCore::runcore()","New Connection Received");
    			if(!UserHandler->AddUser(*nsfd,"unsupported"))
    			{
    				ErrorHandler->ProduceError(0,"cSCore::runcore()","Failed To Add User");
    				close(*nsfd);
    			}
    			else
    			{
    				info("cSCore::runcore()","Adding to FD Set");
    			FD_SET(*nsfd,master);
    			if(*nsfd > *maxfd)
    				*maxfd = *nsfd;
    			}
    				
    		}
    		else
    		{
    			ErrorHandler->ProduceError(0,"cSCore::runcore()","Data Received");
    			tempuser = UserHandler->GetUser(0);
    			//ErrorHandler->ProduceError(0,"cSCore::runcore()","UserPtr Caught");
    			while(tempuser != NULL)
    			{
    				//ErrorHandler->ProduceError(0,"cSCore::runcore()","looping list");
    				/*A User wants to send something*/
    				if(FD_ISSET(tempuser->sfd,cset) && tempuser->sfd != *lsfd)
    				{
    					*nsfd = tempuser->sfd;
    					ErrorHandler->ProduceError(0,"cSCore::runcore()","reading data");
    					returnval = Socket->cs_read(*nsfd,charbuffer,1);
    					//printf("Buffer value: %d\n",int(charbuffer[0]));
    					//Check For Disconnects
    					if(returnval == 0)
    					{
    						
    						
    						ChannelHandler->UserDisconnected(*nsfd);
    						info("cSCore::runcore()","User Disconnected From Channels");
    						UserHandler->RemoveUser(*nsfd);
    						info("cSCore::runcore()","User Disconnected");
    						
    						close(*nsfd);
    						FD_CLR(*nsfd,master);
    						if(UserHandler->numusers == 0)
    						{
    							FD_ZERO(master);
    							FD_SET(*lsfd,master);
    						}
    						break;
    						
    					}
    					else
    					{
    						if(int(charbuffer[0]) == -1) //Byte 255
    						{
    							this->parsecmd(*nsfd,tempuser->UserBuffer->buffer);
    							(tempuser->UserBuffer->done) = true;
    						}
    						else if((tempuser->UserBuffer->strsize) < ((tempuser->UserBuffer->buffersize) - 1))
    						{
    							tempuser->UserBuffer->buffer[(tempuser->UserBuffer->strsize)] = charbuffer[0];
    							(tempuser->UserBuffer->strsize)++;
    						}
    						else if((tempuser->UserBuffer->buffersize) < 512)
    						{
    							(tempuser->UserBuffer->buffersize) += 5;
    							buffer = new char[(tempuser->UserBuffer->buffersize)];
    							memset(buffer,0,(tempuser->UserBuffer->buffersize));
    							char *temp = tempuser->UserBuffer->buffer;
    							strcpy(buffer,temp);
    							buffer[(tempuser->UserBuffer->strsize)] = charbuffer[0];
    							(tempuser->UserBuffer->strsize)++;
    							tempuser->UserBuffer->buffer = buffer;
    							delete [] temp;
    							
    						}
    						else
    						{
    							(tempuser->UserBuffer->done) = true;
    						}
    						
    						if((tempuser->UserBuffer->done) == true)
    						{
    							char *temp = tempuser->UserBuffer->buffer;
    							tempuser->UserBuffer->buffer = new char[10];
    							memset(tempuser->UserBuffer->buffer,0,10);
    							(tempuser->UserBuffer->strsize) = 0;
    							(tempuser->UserBuffer->buffersize) = 10;
    							(tempuser->UserBuffer->done) = false;
    							delete [] temp;
    						}
    					
    					
    					}
    					break;
    				}
    				tempuser=tempuser->next;
    			}
    
    		}
    		
    	}
    	close(*lsfd);
    	delete master;
    	delete cset;
    	delete nsfd;
    	delete maxfd;
    	delete lsfd;
    	delete [] buffer;
    }
    Thanks

  2. #2
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    You aren't even checking the return value of select. If select is giving you an error, you wouldn't even know it.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    delete master;
    delete cset;
    delete nsfd;
    delete maxfd;
    delete lsfd;
    delete [] buffer;
    All these are small variables - dynamic allocation of them is pretty pointless.

    > char *charbuffer = new char[1];
    This is especially pointless. You also don't delete it, but you do delete buffer, which is probably not what you wanted.

    Try splitting the code into several smaller functions. You have so much code, with so much indentation that it's hard to see what is going on.
    Using tabs for indentation is a bit of a problem on this board, since the default tabstop width is quite large, thus exagerating the amount of indentation.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Jul 2002
    Posts
    47
    Alright,
    Thanks for the help,
    I just realized what you meant about me deleting buffer instead of charbuffer.

    I know that the allocation is minimal, but the program is so huge that I am trying to keep as much out of the stack as possible. I do know that it is crashing here though. I am going to try reading the return value of select and see what that gets me.

    Thanks,

    Is there a max connections on Select?
    and if so what is the limit?

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > Is there a max connections on Select?
    Yes
    Code:
    /* Maximum number of file descriptors in `fd_set'.  */
    #define FD_SETSIZE              __FD_SETSIZE
    > I do know that it is crashing here though.
    Yeah, but if you're trashing memory, this is almost certainly not the cause (only the effect)

    > I am trying to keep as much out of the stack as possible.
    Unless you're working with large arrays, I don't think its worth doing - certainly not if you're going to end up causing memory leaks with faulty memory allocation and deletion.

    > tempuser->UserBuffer->done
    If you create a couple of functions to hide all this detail, the code will be a lot clearer

    Like
    Code:
    AddCharToUserBuffer( tempuser, ch );
    MarkUserBufferComplete( tempuser );
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Jul 2002
    Posts
    47
    Alright,
    I did check the select and hers what I got
    after the last connection before it segfaults select returns a 1 but the loop does not find a new connection or any data to be read. Then it does the same thing a second time and after that seg faults..
    also here is a bit of cleaned up code.
    Code:
    /****************************************************************/
    /*		FileName: cSCore.cpp				*/
    /*		Author: David Estes(Chrono)			*/
    /*		CopyRight 2004,2005 David Estes			*/
    /*		Under the GPL License				*/
    /*		FOR NON-COMMERCIAL USE ONLY			*/
    /****************************************************************/
    //====================
    //Revisement History |
    //====================
    //02/23/2005 -- Moved Several Functions into cSCore-2.cpp to make file smaller
    //
    //
    //====================
    #include"cSCore.h"
    #include"getarg.h"
    void cSCore::runcore(void)
    {
    	/*Lets Initialize Some Variables*/
    	int lsfd; //Listening File Descriptor
    	int nsfd; //Sfd For New Connections
    	int returnval;
    	int maxfd = 0;
    	char *buffer; //Temporary Message Buffer
    	char *charbuffer = new char[1];
    	struct sockaddr_in newc;
    	fd_set *cset = new fd_set;
    	fd_set *master = new fd_set;
    	memset(charbuffer,0,1);
    	lsfd = Socket->cs_serve(Port);
    	int optval = 1;
    	setsockopt(lsfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));
    	setsockopt(lsfd,SOL_SOCKET,SO_LINGER,&optval,sizeof(optval));
    	//FD_ZERO(cset);
    	FD_ZERO(master);
    	FD_ZERO(cset);
    	FD_SET(lsfd, master); //Add the listening sfd to the FD set
    	maxfd = lsfd;
    	sMainUsers *tempuser;
    	int SelReturnVal=0;
    	printf("Max FD_SIZE = %d\n",FD_SETSIZE);
    	while(enabled)
    	{
    
    		*cset = *master;	
    		SelReturnVal = select((maxfd)+1,cset,NULL,NULL,NULL);
    		printf("Select Returned %d\n",SelReturnVal);
    		if(FD_ISSET(lsfd, cset)) //If It is a New Connection
    		{
    			nsfd = accept(lsfd,NULL,(socklen_t *)sizeof(newc));
    			ErrorHandler->ProduceError(0,"cSCore::runcore()","New Connection Received");
    			if(!UserHandler->AddUser(nsfd,"unsupported"))
    			{
    				ErrorHandler->ProduceError(0,"cSCore::runcore()","Failed To Add User");
    				close(nsfd);
    			}
    			else
    			{
    				info("cSCore::runcore()","Adding to FD Set");
    			FD_SET(nsfd,master);
    			if(nsfd > maxfd)
    				maxfd = nsfd;
    			}
    				
    		}
    		else
    		{
    			ErrorHandler->ProduceError(0,"cSCore::runcore()","Data Received");
    			tempuser = UserHandler->GetUser(0);
    			//ErrorHandler->ProduceError(0,"cSCore::runcore()","UserPtr Caught");
    			while(tempuser != NULL)
    			{
    				//ErrorHandler->ProduceError(0,"cSCore::runcore()","looping list");
    				/*A User wants to send something*/
    				if(FD_ISSET(tempuser->sfd,cset) && tempuser->sfd != lsfd)
    				{
    					nsfd = tempuser->sfd;
    					ErrorHandler->ProduceError(0,"cSCore::runcore()","reading data");
    					returnval = Socket->cs_read(nsfd,charbuffer,1);
    					if(returnval == 0) //Check To See If The User Disconnected
    					{
    						
    						//UserDisconnected -- Notify Channels	
    						ChannelHandler->UserDisconnected(nsfd);
    						info("cSCore::runcore()","User Disconnected From Channels");
    						//Notify UserHandler Of Disconnect and Remove All Memory Allocation of User
    						UserHandler->RemoveUser(nsfd);
    						info("cSCore::runcore()","User Disconnected");
    						close(nsfd);
    						FD_CLR(nsfd,master);
    						printf("%s%sUsers Connected: %d%s\n",FOREBLACK,BACKGREEN,UserHandler->numusers,NORMAL);
    						if(UserHandler->numusers == 0)
    						{
    							FD_ZERO(master);
    							FD_SET(lsfd,master);
    						}
    						break;
    						
    					}
    					else
    					{
    						sUserBuffers *UserBuffer = tempuser->UserBuffer;
    						if(int(charbuffer[0]) == -1) //Byte 255
    						{
    							this->parsecmd(nsfd,GetUserBufferData(UserBuffer));
    							MarkUserBufferComplete(UserBuffer);
    						}
    						else
    						{
    							if(AddCharToUserBuffer(UserBuffer,charbuffer[0]) == -1)
    								MarkUserBufferComplete(UserBuffer);
    						}
    						
    						if(IsBufferComplete(UserBuffer))
    							ResetUserBuffer(UserBuffer);	
    					
    					}
    					break;
    				}
    				tempuser=tempuser->next;
    			}
    
    		}
    		
    	}
    	close(lsfd);
    	delete master;
    	delete cset;
    	delete [] charbuffer;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. temperature sensors
    By danko in forum C Programming
    Replies: 22
    Last Post: 07-10-2007, 07:26 PM
  2. brace-enclosed error
    By jdc18 in forum C++ Programming
    Replies: 53
    Last Post: 05-03-2007, 05:49 PM
  3. Directional Keys - Useing in Console
    By RoD in forum C++ Programming
    Replies: 38
    Last Post: 10-06-2002, 04:42 PM
  4. FAQ: Directional Keys - Useing in Console
    By RoD in forum FAQ Board
    Replies: 38
    Last Post: 10-06-2002, 04:42 PM