+ 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 (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")

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)); 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 */