Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 Apr 2000 10:31:35 -0700
From:      Alfred Perlstein <bright@wintelcom.net>
To:        Sean Peck <speck@news1.newsindex.com>
Cc:        freebsd-hackers@FreeBSD.ORG
Subject:   Re: FreeBSD 3.3 fork/Exec bug?
Message-ID:  <20000408103135.Z4381@fw.wintelcom.net>
In-Reply-To: <Pine.BSI.3.95.1000408122156.882A-100000@news1.newsindex.com>; from speck@news1.newsindex.com on Sat, Apr 08, 2000 at 12:38:20PM -0400
References:  <20000408084711.W4381@fw.wintelcom.net> <Pine.BSI.3.95.1000408122156.882A-100000@news1.newsindex.com>

next in thread | previous in thread | raw e-mail | index | archive | help
* Sean Peck <speck@news1.newsindex.com> [000408 09:47] wrote:
> Alfred,
> 
>   Here is the code being used.

ew. :P  There seems to be some problems in your tcp connect library...

>  while((result !=1)&&(result!=TCP_CONNECT_NONE)&&(timeout!=10)){
>   result = tcp_get_conn(localhostname,port1,10,&sock1);
>   if(result==TCP_CONNECT_TIMEOUT){timeout++;}
>  }
>  printf("result %d\n",result);  //This is coming back 1 in both the
> 			        // fork/execlp and in direct from shell
> 				// running
>  printf("ERRNO %d\n",errno);   // this is coming back 36 in both shell and
> 				// fork/execlp

36 is EINPROGRESS, somehow your connect function isn't handling non-blocking
connects properly.

> Here is the tcp_get_connection() code
> 
> /*
>  * given a HOST name and service PORT number, return connected TCP
>  * socket to the requested service at the requested host.  It will
>  * timeout after SECS (if < 0 then hang).  Passes back socket in SOCKP
>  * and returns error codes.
>  */
> 
> /* tcp_get_conn return codes */
> #define TCP_NO_ERROR		1		/* no error */
> #define TCP_NOT_FOUND		2		/* host not found */
> #define TCP_SOCKET_FAILURE	3		/* socket create failure
> */
> #define TCP_CONNECT_ERROR	4		/* socket connect error */
> #define TCP_CONNECT_TIMEOUT	5		/* socket connect timeout
> */
> #define TCP_CONNECT_NONE	6		/* socket didn't connect
> */
> #define TCP_TRANSFER_ERROR	7		/* read/write error */
> 
> EXPORT	int	tcp_get_conn(const char * host, const int port,
> 			     const int secs, int * sockp)
> {
>   struct sockaddr_in	sadr;
>   struct hostent	*hostp;
>   struct timeval	timeout, *timeoutp;
>   fd_set		fds;
>   char			**addrp, okay = 0;
>   int			sock, ret;
> #ifdef __osf__
>   struct itimerval	timer;
> #endif
>   
>   /* locate host */
>   hostp = gethostbyname(host);
>   if (hostp == NULL)
>     return TCP_NOT_FOUND;
>   
>   /* setup internet port */
>   sadr.sin_family = (u_short)AF_INET;
>   sadr.sin_port = htons(port);
>   
>   sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
>   if (sock < 0)
>     return TCP_SOCKET_FAILURE;
>   
> #ifndef __osf__
>   /* make the fd non-blocking */
>   (void)fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
> #endif
>   
>   if (secs < 0)
>     timeoutp = 0L;
>   else
>     timeoutp = &timeout;
>   FD_ZERO(&fds);
>   
>   /* try to connect to the remote server */
>   for (addrp = hostp->h_addr_list; *addrp != NULL; addrp++) {
>     (void)memcpy((void *)&sadr.sin_addr, *addrp, sizeof(sadr.sin_addr));
> 
> #ifdef __osf__
>     /* set the timer */
>     timer.it_interval = timeout;
>     setitimer(ITIMER_REAL, &timer, NULL);
>     (void)signal(SIGALRM, catch_alarm);
>     alarm_caught = FALSE;
> #endif
>     
>     /* connect or start the connection */
>     ret = connect(sock, (void *)&sadr, sizeof(sadr));
> 
> #ifdef __osf__
>     /* disable the timer */
>     timer.it_value.tv_sec = 0;
>     timer.it_value.tv_usec = 0;
>     setitimer(ITIMER_REAL, &timer, NULL);
>     (void)signal(SIGALRM, SIG_IGN);
> #endif
> 
>     if (ret == 0) {
>       okay = 1;
>       break;
>     }
> 
> #ifdef __osf__
>     (void)close(sock);
>     
>     if (alarm_caught)
>       return TCP_CONNECT_TIMEOUT;
>     else
>       return TCP_CONNECT_ERROR;
> #endif
> 
>     /* not waiting for connection? */
> 
>     if (errno != EINPROGRESS && errno != EWOULDBLOCK) {
>       /* connection refused? */
> 
>       if (errno == ECONNREFUSED)
> 	continue;
> 
>       /* otherwise error */
>       (void)close(sock);
>       return TCP_CONNECT_ERROR;
>     }
>     
>     for (;;) {

FD_ZERO here?

>       FD_SET(sock, &fds);
>       if (secs >= 0) {
> 	timeout.tv_sec = secs;
> 	timeout.tv_usec = 0;
>       }
>       
>       ret = select(sock + 1, 0L, &fds, 0L, timeoutp);

0L -> NULL please :)

>       if (ret > 0 && FD_ISSET(sock, &fds)) {
> 	okay = 1;
> 	break;
>       }
>       if (ret == 0) {
> 	(void)close(sock);
> 	return TCP_CONNECT_TIMEOUT;
>       }
>       if (ret < 0 && errno != EINTR) {
> 	(void)close(sock);
> 	return TCP_CONNECT_ERROR;
>       }
>     }
>     
>     if (okay)
>       break;
>   }
>   
>   /* connection made? */
>   if (okay) {
> #ifndef __osf__
>     /* turn off non-blocking */
>     (void)fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) & ~O_NONBLOCK);
> #endif
>     *sockp = sock;
>     return TCP_NO_ERROR;
>   }
>   
>   (void)close(sock);
>   return TCP_CONNECT_NONE;
> }
> 

Pick up a copy of Unix Netork Programming vol I, see page 411, it
has a very good example on how to do non-blocking connects properly.

-- 
-Alfred Perlstein - [bright@wintelcom.net|alfred@freebsd.org]
"I have the heart of a child; I keep it in a jar on my desk."


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000408103135.Z4381>