Thread: select() problem

  1. #1
    Registered User
    Join Date
    Apr 2005
    Posts
    134

    select() problem

    OS: Linux
    Complier: gcc

    I have a TCP listener which accept multiple TCP connections from the server. I am using select() to multiplex these connections. However, my select() always fails in the recv() part of the code. I can see in the application log that all the TCP connections (total 4) are being received from server. But When actual data is sent from server, selec() fails with "bad descriptor" message. Can someone help me out here?


    Here is my select() loop. Sorry for the big code.

    Code:
    tv.tv_sec = 0;
    tv.tv_usec = 0;
    if (listen(tcpthread->tcpsocket, BACKLOG) == -1) 
    {
        perror("listen");
        pthread_exit(NULL);
    }
       memset(debugstr,'\0',sizeof(debugstr));
       sprintf(debugstr,"Listening..\n\n");
       dbgtrace(__FUNCTION__,debugstr);
       undbgtrace(__FUNCTION__,debugstr);
    	
       FD_SET(tcpthread->tcpsocket,&master);
       fdmax=tcpthread->tcpsocket;
    for (;;)
    {
        read_fds=master;
        if ((nb=select(fdmax+1,&read_fds,NULL,NULL,&tv)) == -1)
        {	
    	perror("select");
    	pthread_exit(NULL);
        }
        for (i=0;i<=fdmax;i++)
       {
            if (FD_ISSET(i,&read_fds))
    	{
    	    if (i == tcpthread->tcpsocket)
    	        {
    		    addrlen=sizeof(XSocket_in);
    		    RemoteSockId=accept(tcpthread->tcpsocket,(XSocket *) &RemoteSock,&addrlen);
    		    if (RemoteSockId < 0)
    		    {
    		         perror("accpet");
    			 pthread_exit(NULL);
    		    } else {
    			 FD_SET(RemoteSockId,&master);
    			 if (RemoteSockId > fdmax)
    			 {
    			     fdmax=RemoteSockId;
    			 }
    						
    			 if (counter < MAX_DISPLAY_CONNS)
    			 {
    			     tcpthread->tcpconns[counter]=(display_t *) malloc (sizeof(display_t));
    			    if (getsockname(RemoteSockId,(XSocket *) &(tcpthread->tcpconns[counter]->local), &sin_size) < 0)
    			    {
    		                perror("getsockname");
    				pthread_exit(NULL);
    			    } 
    
    			    memset(srcip,'\0',sizeof(srcip));
        	           strcpy(srcip,inet_ntoa(tcpthread->tcpconns[counter]->local.sin_addr));
    							
    
    			if (getpeername(RemoteSockId,(XSocket *) &(tcpthread->tcpconns[counter]->remote),&sin_size) < 0)
    			{
    			    perror("getpeername");
    			    pthread_exit(NULL);
    			} 
    
    			memset(dstip,'\0',sizeof(dstip));		strcpy(dstip,inet_ntoa(tcpthread->tcpconns[counter]->remote.sin_addr));
    
    			memset(debugstr,'\0',sizeof(debugstr));
    			sprintf(debugstr,"Thread-%d: Display TCP Connection from Remote %s/%d Local %s/%d Socket: %d \n",pthread_self(),dstip, ntohs(tcpthread->tcpconns[counter]->remote.sin_port),srcip,ntohs(tcpthread->tcpconns[counter]->local.sin_port),RemoteSockId);
    			dbgtrace(__FUNCTION__,debugstr);
    			undbgtrace(__FUNCTION__,debugstr);
    			counter++;
                      }     
       		  if (counter == (MAX_DISPLAY_CONNS - 1))
    		  {
    		       pthread_mutex_lock(&count_mutex);
    		       activecount++;
    		       pthread_mutex_unlock(&count_mutex);
    		       tcpthread->status=OPEN;
    		   } else {
    			tcpthread->status=NOTOPEN;
    		   }
    						
    		}
                } else {
    			bytes_received = (i,(char *)databuff,sizeof(databuff),0);
    			if (bytes_received < 0)
    			{
    		  	     perror("recv");
    			     FD_CLR(i,&read_fds);
    			     close(i);
         			     for (j=0;j<MAX_DISPLAY_CONNS;j++)
    			     {
    			         free(tcpthread->tcpconns[j]);
    				 tcpthread->tcpconns[j] = NULL;
    				 if (delete_conn_from_list(&tcpthread) == TRUE)
    				{
    				    memset(debugstr,'\0',sizeof(debugstr));
    				    sprintf(debugstr,"Connection Entry removed\n");
    				    dbgtrace(__FUNCTION__,debugstr);
    				}
    			 }
    			pthread_mutex_lock(&count_mutex);
    			activecount--;
    			pthread_mutex_unlock(&count_mutex);
    			pthread_exit(NULL);
    		} else if (bytes_received == 0)
    		{
    		     FD_CLR(i,&read_fds);
    		     close(i);
     		     disconnect++;
    		    if (disconnect == MAX_DISPLAY_CONNS)
    		    {
    			for (j=0;i<MAX_DISPLAY_CONNS;j++)
    			{
    			    free(tcpthread->tcpconns[j]);
    			    tcpthread->tcpconns[j] = NULL;
    			    if (delete_conn_from_list(&tcpthread) == TRUE)
    			    {
    				memset(debugstr,'\0',sizeof(debugstr));
    				sprintf(debugstr,"Connection Entry removed\n");
    				dbgtrace(__FUNCTION__,debugstr);
    			     }
    			}
    			pthread_mutex_lock(&count_mutex);
    			activecount--;
    			pthread_mutex_unlock(&count_mutex);
    			pthread_exit(NULL);
    		    }
    		} else {
    		     memset(debugstr,'\0',sizeof(debugstr));
    		     sprintf(debugstr,"Thread-%d: %d bytes received\n", pthread_self() , bytes_received);
    		     dbgtrace(__FUNCTION__,debugstr);
    		     printBuffer(databuff,bytes_received);
    		     tcpthread->bytesin+=bytes_received;
    
    		     bytes_sent = send(i,(char *)databuff,sizeof(databuff),0);
    		     if (bytes_sent < 0)
    		     {
    			perror("send");
    			FD_CLR(i,&read_fds);
    			close(i);
    			for (j=0;j<MAX_DISPLAY_CONNS;j++)
    			{
       			    free(tcpthread->tcpconns[j]);
    			    tcpthread->tcpconns[j] = NULL;
    			    if (delete_conn_from_list(&tcpthread) == TRUE)
    			    {
    				memset(debugstr,'\0',sizeof(debugstr));
    				sprintf(debugstr,"Connection Entry removed\n");
    				bgtrace(__FUNCTION__,debugstr);
    			     }
    			}
    			pthread_mutex_lock(&count_mutex);
    			activecount--;
    			pthread_mutex_unlock(&count_mutex);
    			pthread_exit(NULL);
    		    } else {
    			memset(debugstr,'\0',sizeof(debugstr));
    			sprintf(debugstr,"Thread-%d: %d bytes sent\n",pthread_self(),bytes_sent);
    			dbgtrace(__FUNCTION__,debugstr);
    			tcpthread->bytesout+=bytes_sent;
    		    }
    	        }
    	    }
            }
        }
    }
    When I run it I see following output on console

    handle_tcp_display_conns : Thread-16387: Display TCP Connection from Remote 10.6.250.60/45870 Local 92.178.18.66/4674 Socket: 7
    handle_tcp_display_conns : Thread-16387: Display TCP Connection from Remote 10.6.250.60/45871 Local 10.6.250.55/6005 Socket: 8
    handle_tcp_display_conns : Thread-16387: Display TCP Connection from Remote 10.6.250.60/45872 Local 10.6.250.55/6005 Socket: 9
    handle_tcp_display_conns : Thread-16387: Display TCP Connection from Remote 10.6.250.60/45873 Local 10.6.250.55/6005 Socket: 10
    select: Bad file descriptor <<< It fails here. expecting data from Server
    Thanks,

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > FD_SET(tcpthread->tcpsocket,&master);
    So where's the FD_ZERO call to make sure there's no rubbish in there?

    I also see some poorly indented code, and a function which is now so massively long that's its impossible to see what is going on.

    > memset(srcip,'\0',sizeof(srcip));
    > strcpy(srcip,inet_ntoa(tcpthread->tcpconns[counter]->local.sin_addr));
    Why the memset, when you know strcpy will copy a \0 for you?
    If there isn't a \0 (and you're trying to get one), then strcpy() isn't the function you should be using. Perhaps you want strncpy()
    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.

  3. #3
    Registered User
    Join Date
    Apr 2005
    Posts
    134
    Quote Originally Posted by Salem
    > FD_SET(tcpthread->tcpsocket,&master);
    So where's the FD_ZERO call to make sure there's no rubbish in there?

    I also see some poorly indented code, and a function which is now so massively long that's its impossible to see what is going on.

    > memset(srcip,'\0',sizeof(srcip));
    > strcpy(srcip,inet_ntoa(tcpthread->tcpconns[counter]->local.sin_addr));
    Why the memset, when you know strcpy will copy a \0 for you?
    If there isn't a \0 (and you're trying to get one), then strcpy() isn't the function you should be using. Perhaps you want strncpy()
    FD_ZERO is there at the top, just that I didn't post it here. Sorry about the confusion.

    memset() is just to make sure is string is empty with no garbage to avoid overlapped strings if strings in each recursion are not of the same length. But since strcpy() will take care of NULL termination, I guess I am better of without it.

    Sorry about the indentation. I posted to the code from EditPlus editor which used tab for indentation. Althogh it looks good in the editor, apprently not so good for posting code here in forum. I had to indent it manually again. Somethings got messed up because of that.

    Other than these do you see any obvious coding error ? How can I see which socket its giving error for?

  4. #4
    Registered User
    Join Date
    Apr 2005
    Posts
    134
    ok problem solved..It was really really really a silly mistake

    while calling function recv() i forgot to mention function name

    Code:
    bytes_received = (i,(char *)databuff,sizeof(databuff),0);
    should be

    Code:
    bytes_received = recv (i,(char *)databuff,sizeof(databuff),0);
    sorry about the trouble.

    Thanks,

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. FAQ: Directional Keys - Useing in Console
    By RoD in forum FAQ Board
    Replies: 38
    Last Post: 10-06-2002, 04:42 PM
  3. beginner problem
    By The_Nymph in forum C Programming
    Replies: 4
    Last Post: 03-05-2002, 05:46 PM
  4. problem with output
    By Garfield in forum C Programming
    Replies: 2
    Last Post: 11-18-2001, 08:34 PM