+ 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