+ 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:
mainzelm 2002-10-30 13:12:00 +00:00
parent 4290ccae21
commit bcd64a2b3a
2 changed files with 30 additions and 36 deletions

View File

@ -227,30 +227,33 @@
(error
"connect: trying to connect socket to incompatible address ~s"
name))
((and (= family address-family/unix)
; save space for \0
(> (string-length (socket-address:address name)) 107))
(error "connect: filename too long" name))
(else
(let loop ()
((structure-ref interrupts disable-interrupts!))
(let* ((fdes (socket->fdes sock))
(res (%connect fdes
(socket:family sock)
(socket-address:address name))))
(cond ((eq? res #t)
((structure-ref interrupts enable-interrupts!)))
(else
(select '#() (vector fdes) '#())
(if (car res)
;; If connect returned EINPROGRESS, we can check
;; it's success after the next success with getsockopt
(let ((val (socket-option sock
level/socket
socket/error)))
(if (not (zero? val))
(errno-error val
(errno-msg val)
%connect
sock
name)))
(loop))))))))))))
(error?.einprogress?
(%connect fdes
(socket:family sock)
(socket-address:address name))))
(if (car error?.einprogress?)
(begin
(select '#() (vector (socket:outport sock)) '#())
(if (cdr error?.einprogress?)
;; If connect returned EINPROGRESS, we can check
;; it's success after the next success with getsockopt
(let ((val (socket-option sock
level/socket
socket/error)))
(if (not (zero? val))
(errno-error val
(errno-msg val)
%connect
sock
name)))
(loop))))))))))))
(import-os-error-syscall %connect (sockfd family name) "scheme_connect")

View File

@ -89,27 +89,20 @@ s48_value scheme_connect(s48_value sock, s48_value family, s48_value scheme_name
memset(&name, 0, sizeof(name));
name.sun_family=AF_UNIX;
if (scheme_length>=(108-1)) /* save space for \0 */
return(-1);
strncpy(name.sun_path,
s48_extract_string (scheme_name),
scheme_length); /* copy to c string */
name.sun_path[scheme_length]='\0'; /* add null */
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
&& errno != EINPROGRESS && errno != EAGAIN)
s48_raise_os_error_3(errno, sock, family, scheme_name);
if (! (s48_add_pending_fd(sockfd, 0)))
s48_raise_out_of_memory_error();
if (errno == EINPROGRESS)
return s48_enter_fixnum (0);
else return S48_FALSE;
return s48_cons (S48_TRUE, (errno == EINPROGRESS) ? S48_TRUE : S48_FALSE);
}
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;
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
&& errno != EINPROGRESS && errno != EAGAIN)
s48_raise_os_error_3(errno, sock, family, scheme_name);
return
s48_cons ((errno == EINPROGRESS) ? S48_TRUE : S48_FALSE,
s48_enter_fixnum (sockfd));
return s48_cons (S48_TRUE, (errno == EINPROGRESS) ? S48_TRUE : S48_FALSE);
}
default:
s48_raise_argument_type_error (family); /* error unknown address family */