+ Use select on socket:outport if connect returned EINPROGRESS.
+ Clearer return values for %connect: return a pair that indicates whether an recoverable error occured and if this error was EINPROGRESS or something else.
This commit is contained in:
		
							parent
							
								
									4290ccae21
								
							
						
					
					
						commit
						bcd64a2b3a
					
				|  | @ -227,30 +227,33 @@ | ||||||
| 		  (error  | 		  (error  | ||||||
| 		   "connect: trying to connect socket to incompatible address ~s" | 		   "connect: trying to connect socket to incompatible address ~s" | ||||||
| 		   name)) | 		   name)) | ||||||
|  | 		 ((and (= family address-family/unix) | ||||||
|  | 		       ; save space for \0 | ||||||
|  | 		       (> (string-length (socket-address:address name)) 107)) | ||||||
|  | 		  (error "connect: filename too long" name)) | ||||||
| 		 (else | 		 (else | ||||||
| 		  (let loop () | 		  (let loop () | ||||||
| 		    ((structure-ref interrupts disable-interrupts!)) |  | ||||||
| 		    (let* ((fdes (socket->fdes sock)) | 		    (let* ((fdes (socket->fdes sock)) | ||||||
| 			   (res (%connect fdes | 			   (error?.einprogress? | ||||||
| 					  (socket:family sock) | 			    (%connect fdes | ||||||
| 					  (socket-address:address name)))) | 				      (socket:family sock) | ||||||
| 		      (cond ((eq? res #t) | 				      (socket-address:address name)))) | ||||||
| 			     ((structure-ref interrupts enable-interrupts!))) | 		      (if (car error?.einprogress?) | ||||||
| 			    (else | 			  (begin | ||||||
| 			     (select '#() (vector fdes) '#()) | 			    (select '#() (vector (socket:outport sock)) '#()) | ||||||
| 			     (if (car res) | 			    (if (cdr error?.einprogress?) | ||||||
| 				 ;; If connect returned EINPROGRESS, we can check  | 				;; If connect returned EINPROGRESS, we can check  | ||||||
| 				 ;; it's success after  the next success with getsockopt | 				;; it's success after  the next success with getsockopt | ||||||
| 				 (let ((val (socket-option sock  | 				(let ((val (socket-option sock  | ||||||
| 							   level/socket  | 							  level/socket  | ||||||
| 							   socket/error))) | 							  socket/error))) | ||||||
| 				   (if (not (zero? val)) | 				  (if (not (zero? val)) | ||||||
| 				       (errno-error val  | 				      (errno-error val  | ||||||
| 						    (errno-msg val)  | 						   (errno-msg val)  | ||||||
| 						    %connect  | 						   %connect  | ||||||
| 						    sock  | 						   sock  | ||||||
| 						    name))) | 						   name))) | ||||||
| 				 (loop)))))))))))) | 				(loop)))))))))))) | ||||||
| 
 | 
 | ||||||
| (import-os-error-syscall %connect (sockfd family name) "scheme_connect") | (import-os-error-syscall %connect (sockfd family name) "scheme_connect") | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -89,27 +89,20 @@ s48_value scheme_connect(s48_value sock, s48_value family, s48_value scheme_name | ||||||
| 	memset(&name, 0, sizeof(name)); | 	memset(&name, 0, sizeof(name)); | ||||||
| 	 | 	 | ||||||
| 	name.sun_family=AF_UNIX;	 | 	name.sun_family=AF_UNIX;	 | ||||||
| 	if (scheme_length>=(108-1)) /* save space for \0 */ | 
 | ||||||
| 	  return(-1); |  | ||||||
| 	strncpy(name.sun_path, | 	strncpy(name.sun_path, | ||||||
| 		s48_extract_string (scheme_name), | 		s48_extract_string (scheme_name), | ||||||
| 		scheme_length);	/* copy to c string */ | 		scheme_length);	/* copy to c string */ | ||||||
| 	name.sun_path[scheme_length]='\0'; /* add null */ | 	name.sun_path[scheme_length]='\0'; /* add null */ | ||||||
| 	 | 	 | ||||||
| 	if (connect(sockfd,(struct sockaddr *)&name,sizeof(name)) == 0) | 	if (connect(sockfd,(struct sockaddr *)&name,sizeof(name)) == 0) | ||||||
| 	  return S48_TRUE; | 	  return s48_cons (S48_FALSE, S48_UNSPECIFIC); | ||||||
| 	 | 	 | ||||||
| 	if (errno != EWOULDBLOCK && errno != EINTR && errno != EALREADY | 	if (errno != EWOULDBLOCK && errno != EINTR && errno != EALREADY | ||||||
| 	    && errno != EINPROGRESS && errno != EAGAIN) | 	    && errno != EINPROGRESS && errno != EAGAIN) | ||||||
| 	  s48_raise_os_error_3(errno, sock, family, scheme_name); | 	  s48_raise_os_error_3(errno, sock, family, scheme_name); | ||||||
| 	  | 	  | ||||||
| 	if (! (s48_add_pending_fd(sockfd, 0))) | 	return s48_cons (S48_TRUE, (errno == EINPROGRESS) ? S48_TRUE : S48_FALSE);	 | ||||||
| 	  s48_raise_out_of_memory_error(); |  | ||||||
| 	 |  | ||||||
| 	if (errno == EINPROGRESS)  |  | ||||||
| 	  return s48_enter_fixnum (0);  |  | ||||||
| 	else return S48_FALSE; |  | ||||||
| 	 |  | ||||||
|       } |       } | ||||||
|     case AF_INET:  |     case AF_INET:  | ||||||
|       { |       { | ||||||
|  | @ -125,15 +118,13 @@ s48_value scheme_connect(s48_value sock, s48_value family, s48_value scheme_name | ||||||
| 	name.sin_port=port; | 	name.sin_port=port; | ||||||
| 	 | 	 | ||||||
| 	if (connect(sockfd,(struct sockaddr *)&name,sizeof(name)) == 0) | 	if (connect(sockfd,(struct sockaddr *)&name,sizeof(name)) == 0) | ||||||
| 	  return S48_TRUE; | 	  return s48_cons (S48_FALSE, S48_UNSPECIFIC); | ||||||
| 	 | 	 | ||||||
| 	if (errno != EWOULDBLOCK && errno != EINTR && errno != EALREADY | 	if (errno != EWOULDBLOCK && errno != EINTR && errno != EALREADY | ||||||
| 	    && errno != EINPROGRESS && errno != EAGAIN) | 	    && errno != EINPROGRESS && errno != EAGAIN) | ||||||
| 	  s48_raise_os_error_3(errno, sock, family, scheme_name); | 	  s48_raise_os_error_3(errno, sock, family, scheme_name); | ||||||
| 
 | 	 | ||||||
| 	return | 	return s48_cons (S48_TRUE, (errno == EINPROGRESS) ? S48_TRUE : S48_FALSE); | ||||||
| 	  s48_cons ((errno == EINPROGRESS) ? S48_TRUE : S48_FALSE, |  | ||||||
| 		    s48_enter_fixnum (sockfd)); |  | ||||||
|       } |       } | ||||||
|     default:  |     default:  | ||||||
|       s48_raise_argument_type_error (family);	/* error unknown address family */  |       s48_raise_argument_type_error (family);	/* error unknown address family */  | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 mainzelm
						mainzelm