diff options
author | trawick <trawick@13f79535-47bb-0310-9956-ffa450edef68> | 2001-07-10 15:01:43 +0000 |
---|---|---|
committer | trawick <trawick@13f79535-47bb-0310-9956-ffa450edef68> | 2001-07-10 15:01:43 +0000 |
commit | 2489186f0f850b96bf0fce72ee2e4520474e52b8 (patch) | |
tree | 859968c65e3b5e0d68f1f8da00186ecefefe79bc /network_io | |
parent | dd2e0eb3ea532af4c69d89153bb711f0c8890ff0 (diff) | |
download | libapr-2489186f0f850b96bf0fce72ee2e4520474e52b8.tar.gz |
apr_connect() on Unix:
handle EINTR
handle APR timeouts on the socket
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@61910 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'network_io')
-rw-r--r-- | network_io/unix/sendrecv.c | 20 | ||||
-rw-r--r-- | network_io/unix/sockets.c | 67 |
2 files changed, 54 insertions, 33 deletions
diff --git a/network_io/unix/sendrecv.c b/network_io/unix/sendrecv.c index 1e9df3d62..abd77409c 100644 --- a/network_io/unix/sendrecv.c +++ b/network_io/unix/sendrecv.c @@ -59,7 +59,7 @@ #include "fileio.h" #endif /* APR_HAS_SENDFILE */ -static apr_status_t wait_for_io_or_timeout(apr_socket_t *sock, int for_read) +apr_status_t apr_wait_for_io_or_timeout(apr_socket_t *sock, int for_read) { struct timeval tv, *tvptr; fd_set fdset; @@ -103,7 +103,7 @@ apr_status_t apr_send(apr_socket_t *sock, const char *buf, apr_size_t *len) if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && sock->timeout != 0) { - apr_status_t arv = wait_for_io_or_timeout(sock, 0); + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0); if (arv != APR_SUCCESS) { *len = 0; return arv; @@ -132,7 +132,7 @@ apr_status_t apr_recv(apr_socket_t *sock, char *buf, apr_size_t *len) if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && sock->timeout != 0) { - apr_status_t arv = wait_for_io_or_timeout(sock, 1); + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 1); if (arv != APR_SUCCESS) { *len = 0; return arv; @@ -167,7 +167,7 @@ apr_status_t apr_sendto(apr_socket_t *sock, apr_sockaddr_t *where, if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && sock->timeout != 0) { - apr_status_t arv = wait_for_io_or_timeout(sock, 0); + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0); if (arv != APR_SUCCESS) { *len = 0; return arv; @@ -200,7 +200,7 @@ apr_status_t apr_recvfrom(apr_sockaddr_t *from, apr_socket_t *sock, if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && sock->timeout != 0) { - apr_status_t arv = wait_for_io_or_timeout(sock, 1); + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 1); if (arv != APR_SUCCESS) { *len = 0; return arv; @@ -235,7 +235,7 @@ apr_status_t apr_sendv(apr_socket_t * sock, const struct iovec *vec, if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && sock->timeout != 0) { - apr_status_t arv = wait_for_io_or_timeout(sock, 0); + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0); if (arv != APR_SUCCESS) { *len = 0; return arv; @@ -324,7 +324,7 @@ apr_status_t apr_sendfile(apr_socket_t *sock, apr_file_t *file, if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && sock->timeout > 0) { - arv = wait_for_io_or_timeout(sock, 0); + arv = apr_wait_for_io_or_timeout(sock, 0); if (arv != APR_SUCCESS) { *len = 0; return arv; @@ -423,7 +423,7 @@ apr_status_t apr_sendfile(apr_socket_t * sock, apr_file_t * file, * we get -1/EAGAIN/nbytes>0; AFAICT it just means extra syscalls * from time to time */ - apr_status_t arv = wait_for_io_or_timeout(sock, 0); + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0); if (arv != APR_SUCCESS) { *len = 0; return arv; @@ -577,7 +577,7 @@ apr_status_t apr_sendfile(apr_socket_t *sock, apr_file_t *file, if (rc == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && sock->timeout > 0) { - apr_status_t arv = wait_for_io_or_timeout(sock, 0); + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0); if (arv != APR_SUCCESS) { *len = 0; @@ -710,7 +710,7 @@ apr_status_t apr_sendfile(apr_socket_t * sock, apr_file_t * file, if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && sock->timeout > 0) { - arv = wait_for_io_or_timeout(sock, 0); + arv = apr_wait_for_io_or_timeout(sock, 0); if (arv != APR_SUCCESS) { *len = 0; return arv; diff --git a/network_io/unix/sockets.c b/network_io/unix/sockets.c index d60712e9e..c14ce5475 100644 --- a/network_io/unix/sockets.c +++ b/network_io/unix/sockets.c @@ -257,39 +257,60 @@ apr_status_t apr_accept(apr_socket_t **new, apr_socket_t *sock, apr_pool_t *conn apr_status_t apr_connect(apr_socket_t *sock, apr_sockaddr_t *sa) { + int rc; + if ((sock->socketdes < 0) || (!sock->remote_addr)) { return APR_ENOTSOCK; } - if ((connect(sock->socketdes, - (const struct sockaddr *)&sa->sa.sin, - sa->salen) < 0) && - (errno != EINPROGRESS)) { + do { + rc = connect(sock->socketdes, + (const struct sockaddr *)&sa->sa.sin, + sa->salen); + } while (rc == -1 && errno == EINTR); + + /* we can see EINPROGRESS the first time connect is called on a non-blocking + * socket; if called again, we can see EALREADY + */ + if (rc == -1 && (errno == EINPROGRESS || errno == EALREADY) && sock->timeout != 0) { + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0); + if (arv != APR_SUCCESS) { + return arv; + } + else { + do { + rc = connect(sock->socketdes, + (const struct sockaddr *)&sa->sa.sin, + sa->salen); + } while (rc == -1 && errno == EINTR); + } + } + + if (rc == -1) { return errno; } - else { - sock->remote_addr = sa; - /* XXX IPv6 assumes sin_port and sin6_port at same offset */ - if (sock->local_addr->sa.sin.sin_port == 0) { - /* connect() got us an ephemeral port */ - sock->local_port_unknown = 1; - } - /* XXX IPv6 to be handled better later... */ - if ( + + sock->remote_addr = sa; + /* XXX IPv6 assumes sin_port and sin6_port at same offset */ + if (sock->local_addr->sa.sin.sin_port == 0) { + /* connect() got us an ephemeral port */ + sock->local_port_unknown = 1; + } + /* XXX IPv6 to be handled better later... */ + if ( #if APR_HAVE_IPV6 - sock->local_addr->sa.sin.sin_family == APR_INET6 || + sock->local_addr->sa.sin.sin_family == APR_INET6 || #endif - sock->local_addr->sa.sin.sin_addr.s_addr == 0) { - /* not bound to specific local interface; connect() had to assign - * one for the socket - */ - sock->local_interface_unknown = 1; - } + sock->local_addr->sa.sin.sin_addr.s_addr == 0) { + /* not bound to specific local interface; connect() had to assign + * one for the socket + */ + sock->local_interface_unknown = 1; + } #ifndef HAVE_POLL - sock->connected=1; + sock->connected=1; #endif - return APR_SUCCESS; - } + return APR_SUCCESS; } apr_status_t apr_socket_data_get(void **data, const char *key, apr_socket_t *sock) |