diff options
author | Jeff Trawick <trawick@apache.org> | 2000-04-16 16:59:39 +0000 |
---|---|---|
committer | Jeff Trawick <trawick@apache.org> | 2000-04-16 16:59:39 +0000 |
commit | 30514c7907998dd5905ec8d1a8e51cee34aec331 (patch) | |
tree | 432707f2d6c9ec82808aa99a723495708970a476 | |
parent | 8d7cc60c98970f66eccdc57ec29d10d855a099b7 (diff) | |
download | apr-30514c7907998dd5905ec8d1a8e51cee34aec331.tar.gz |
APR_SO_TIMEOUT now takes microseconds instead of seconds. (The new
CHANGES text also reflects prior work on ap_poll() and
ap_set_pipe_timeout()).
apr/test/client.c now has a crude command-line mechanism for selecting
a read timeout.
Included bug fixes:
1) Some storage leaks were removed in BeOS and Unix select() usage.
2) For Win32, the code to process APR_SO_TIMEOUT stored timeout in
milliseconds but the code to timeout a TransmitFile() in
ap_sendfile() assumed that it had been stored in seconds.
3) ab_apr.c used a 30,000-second timeout in one place. This was
changed to a 30-second timeout.
4) fix bad perldoc comment in apr_network_io.h which hid the
ap_shutdown() prototype
5) disable stdout buffering in apr/test/client.c so that messages
appear in the correct order when an error occurs
git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@59870 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | include/apr_network_io.h | 6 | ||||
-rw-r--r-- | include/arch/beos/networkio.h | 2 | ||||
-rw-r--r-- | include/arch/os2/networkio.h | 2 | ||||
-rw-r--r-- | include/arch/unix/networkio.h | 2 | ||||
-rw-r--r-- | include/arch/win32/networkio.h | 2 | ||||
-rw-r--r-- | network_io/beos/networkio.h | 2 | ||||
-rw-r--r-- | network_io/beos/sendrecv.c | 24 | ||||
-rw-r--r-- | network_io/os2/networkio.h | 2 | ||||
-rw-r--r-- | network_io/os2/sendrecv.c | 6 | ||||
-rw-r--r-- | network_io/unix/networkio.h | 2 | ||||
-rw-r--r-- | network_io/unix/sendrecv.c | 51 | ||||
-rw-r--r-- | network_io/win32/networkio.h | 2 | ||||
-rw-r--r-- | network_io/win32/sendrecv.c | 6 | ||||
-rw-r--r-- | network_io/win32/sockopt.c | 5 | ||||
-rw-r--r-- | test/ab_apr.c | 4 | ||||
-rw-r--r-- | test/client.c | 35 |
16 files changed, 80 insertions, 73 deletions
diff --git a/include/apr_network_io.h b/include/apr_network_io.h index 492801f08..3b418b23d 100644 --- a/include/apr_network_io.h +++ b/include/apr_network_io.h @@ -166,7 +166,7 @@ B<NOTE>: This does not actually close the socket descriptor, it just controls which calls are still valid on the socket. =cut - / + */ ap_status_t ap_shutdown(ap_socket_t *ithesocket, ap_shutdown_how_e how); /* @@ -381,7 +381,7 @@ B<Read data from a network.> arg 3) On entry, the number of bytes to receive; on exit, the number of bytes received. -B<NOTE>: This functions acts like a blocking write by default. To change +B<NOTE>: This functions acts like a blocking read by default. To change this behavior, use ap_setsocketopt with the APR_SO_TIMEOUT option. The number of bytes actually sent is stored in argument 3. @@ -409,7 +409,7 @@ B<Setup socket options for the specified socket> APR_SO_REUSEADDR -- The rules used in validating addresses supplied to bind should allow reuse of local addresses. - APR_SO_TIMEOUT -- Set the timeout value in seconds. + APR_SO_TIMEOUT -- Set the timeout value in microseconds. values < 0 mean wait forever. 0 means don't wait at all. APR_SO_SNDBUF -- Set the SendBufferSize diff --git a/include/arch/beos/networkio.h b/include/arch/beos/networkio.h index e971e489f..3966acf43 100644 --- a/include/arch/beos/networkio.h +++ b/include/arch/beos/networkio.h @@ -91,7 +91,7 @@ struct ap_socket_t { struct sockaddr_in *local_addr; struct sockaddr_in *remote_addr; int addr_len; - int timeout; + ap_interval_time_t timeout; int connected; }; diff --git a/include/arch/os2/networkio.h b/include/arch/os2/networkio.h index c0be3720b..63424de6a 100644 --- a/include/arch/os2/networkio.h +++ b/include/arch/os2/networkio.h @@ -65,7 +65,7 @@ struct ap_socket_t { struct sockaddr_in *local_addr; struct sockaddr_in *remote_addr; int addr_len; - int timeout; + ap_interval_time_t timeout; int nonblock; }; diff --git a/include/arch/unix/networkio.h b/include/arch/unix/networkio.h index 951c045a7..bfb08f854 100644 --- a/include/arch/unix/networkio.h +++ b/include/arch/unix/networkio.h @@ -112,7 +112,7 @@ struct ap_socket_t { struct sockaddr_in *local_addr; struct sockaddr_in *remote_addr; socklen_t addr_len; - int timeout; + ap_interval_time_t timeout; #ifndef HAVE_POLL int connected; #endif diff --git a/include/arch/win32/networkio.h b/include/arch/win32/networkio.h index 5421312e2..58d82f8b1 100644 --- a/include/arch/win32/networkio.h +++ b/include/arch/win32/networkio.h @@ -64,7 +64,7 @@ struct ap_socket_t { struct sockaddr_in *local_addr; struct sockaddr_in *remote_addr; size_t addr_len; - int timeout; + ap_interval_time_t timeout; }; struct ap_pollfd_t { diff --git a/network_io/beos/networkio.h b/network_io/beos/networkio.h index e971e489f..3966acf43 100644 --- a/network_io/beos/networkio.h +++ b/network_io/beos/networkio.h @@ -91,7 +91,7 @@ struct ap_socket_t { struct sockaddr_in *local_addr; struct sockaddr_in *remote_addr; int addr_len; - int timeout; + ap_interval_time_t timeout; int connected; }; diff --git a/network_io/beos/sendrecv.c b/network_io/beos/sendrecv.c index 9845f4691..995a8e5c7 100644 --- a/network_io/beos/sendrecv.c +++ b/network_io/beos/sendrecv.c @@ -63,7 +63,7 @@ ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len) } while (rv == -1 && errno == EINTR); if (rv == -1 && errno == EAGAIN && sock->timeout > 0) { - struct timeval *tv; + struct timeval tv, *tvptr; fd_set fdset; int srv; @@ -71,14 +71,14 @@ ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len) FD_ZERO(&fdset); FD_SET(sock->socketdes, &fdset); if (sock->timeout == -1) - tv = NULL; + tvptr = NULL; else { - tv = (struct timeval *)ap_palloc(sock->cntxt, sizeof(struct timeval)); - tv->tv_sec = sock->timeout; - tv->tv_usec = 0; + tv.tv_sec = sock->timeout / AP_USEC_PER_SEC; + tv.tv_usec = sock->timeout % AP_USEC_PER_SEC; + tvptr = &tv; } - srv = select(FD_SETSIZE, NULL, &fdset, NULL, tv); + srv = select(FD_SETSIZE, NULL, &fdset, NULL, tvptr); } while (srv == -1 && errno == EINTR); if (srv == 0) { @@ -108,7 +108,7 @@ ap_status_t ap_recv(ap_socket_t *sock, char *buf, ap_ssize_t *len) } while (rv == -1 && errno == EINTR); if (rv == -1 && errno == EAGAIN && sock->timeout > 0) { - struct timeval *tv; + struct timeval tv, *tvptr; fd_set fdset; int srv; @@ -116,14 +116,14 @@ ap_status_t ap_recv(ap_socket_t *sock, char *buf, ap_ssize_t *len) FD_ZERO(&fdset); FD_SET(sock->socketdes, &fdset); if (sock->timeout == -1) - tv = NULL; + tvptr = NULL; else { - tv = (struct timeval *)ap_palloc(sock->cntxt, sizeof(struct timeval)); - tv->tv_sec = sock->timeout; - tv->tv_usec = 0; + tv.tv_sec = sock->timeout / AP_USEC_PER_SEC; + tv.tv_usec = sock->timeout % AP_USEC_PER_SEC; + tvptr = &tv; } - srv = select(FD_SETSIZE, &fdset, NULL, NULL, tv); + srv = select(FD_SETSIZE, &fdset, NULL, NULL, tvptr); } while (srv == -1 && errno == EINTR); if (srv == 0) { diff --git a/network_io/os2/networkio.h b/network_io/os2/networkio.h index c0be3720b..63424de6a 100644 --- a/network_io/os2/networkio.h +++ b/network_io/os2/networkio.h @@ -65,7 +65,7 @@ struct ap_socket_t { struct sockaddr_in *local_addr; struct sockaddr_in *remote_addr; int addr_len; - int timeout; + ap_interval_time_t timeout; int nonblock; }; diff --git a/network_io/os2/sendrecv.c b/network_io/os2/sendrecv.c index 2cc2293b1..a2bf14429 100644 --- a/network_io/os2/sendrecv.c +++ b/network_io/os2/sendrecv.c @@ -67,7 +67,7 @@ ap_status_t ap_send(ap_socket_t *sock, const char *buf, ap_ssize_t *len) do { if (!sock->nonblock || err == SOCEWOULDBLOCK) { fds = sock->socketdes; - rv = select(&fds, 0, 1, 0, sock->timeout >= 0 ? sock->timeout*1000 : -1); + rv = select(&fds, 0, 1, 0, sock->timeout >= 0 ? sock->timeout/1000 : -1); if (rv != 1) { *len = 0; @@ -106,7 +106,7 @@ ap_status_t ap_recv(ap_socket_t *sock, char *buf, ap_ssize_t *len) do { if (!sock->nonblock || err == SOCEWOULDBLOCK) { fds = sock->socketdes; - rv = select(&fds, 1, 0, 0, sock->timeout >= 0 ? sock->timeout*1000 : -1); + rv = select(&fds, 1, 0, 0, sock->timeout >= 0 ? sock->timeout/1000 : -1); if (rv != 1) { *len = 0; @@ -149,7 +149,7 @@ ap_status_t ap_sendv(ap_socket_t *sock, const struct iovec *vec, ap_int32_t nvec do { if (!sock->nonblock || err == SOCEWOULDBLOCK) { fds = sock->socketdes; - rv = select(&fds, 0, 1, 0, sock->timeout >= 0 ? sock->timeout*1000 : -1); + rv = select(&fds, 0, 1, 0, sock->timeout >= 0 ? sock->timeout/1000 : -1); if (rv != 1) { *len = 0; diff --git a/network_io/unix/networkio.h b/network_io/unix/networkio.h index 951c045a7..bfb08f854 100644 --- a/network_io/unix/networkio.h +++ b/network_io/unix/networkio.h @@ -112,7 +112,7 @@ struct ap_socket_t { struct sockaddr_in *local_addr; struct sockaddr_in *remote_addr; socklen_t addr_len; - int timeout; + ap_interval_time_t timeout; #ifndef HAVE_POLL int connected; #endif diff --git a/network_io/unix/sendrecv.c b/network_io/unix/sendrecv.c index 0b6b1241b..be163461a 100644 --- a/network_io/unix/sendrecv.c +++ b/network_io/unix/sendrecv.c @@ -69,20 +69,27 @@ static ap_status_t wait_for_io_or_timeout(ap_socket_t *sock, int for_read) { - struct timeval tv; + struct timeval tv, *tvptr; fd_set fdset; int srv; do { FD_ZERO(&fdset); FD_SET(sock->socketdes, &fdset); - tv.tv_sec = sock->timeout; - tv.tv_usec = 0; - srv = select(FD_SETSIZE, + if (sock->timeout < 0) { + tvptr = NULL; + } + else { + tv.tv_sec = sock->timeout / AP_USEC_PER_SEC; + tv.tv_usec = sock->timeout % AP_USEC_PER_SEC; + tvptr = &tv; + } + srv = select(sock->socketdes + 1, for_read ? &fdset : NULL, for_read ? NULL : &fdset, NULL, - sock->timeout < 0 ? NULL : &tv); + tvptr); + /* TODO - timeout should be smaller on repeats of this loop */ } while (srv == -1 && errno == EINTR); if (srv == 0) { @@ -400,34 +407,12 @@ ap_status_t ap_sendfile(ap_socket_t * sock, ap_file_t * file, if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && sock->timeout != 0) { - struct timeval *tv; - fd_set fdset; - int srv; - - do { - FD_ZERO(&fdset); - FD_SET(sock->socketdes, &fdset); - if (sock->timeout < 0) { - tv = NULL; - } - else { - /* XXX: BUHHH? wow, what a memory leak! */ - tv = ap_palloc(sock->cntxt, sizeof(struct timeval)); - tv->tv_sec = sock->timeout; - tv->tv_usec = 0; - } - srv = select(FD_SETSIZE, NULL, &fdset, NULL, tv); - } while (srv == -1 && errno == EINTR); - - if (srv == 0) { - /* XXX: -1 is wrong */ - (*len) = -1; - return APR_TIMEUP; - } - else if (srv < 0) { - /* XXX: -1 is wrong */ - (*len) = -1; - return errno; + ap_status_t arv = wait_for_io_or_timeout(sock, 0); + + if (arv != APR_SUCCESS) { + /* jlt: not tested, but this matches other sendfile logic */ + (*len) = 0; + return arv; } else { do { diff --git a/network_io/win32/networkio.h b/network_io/win32/networkio.h index 5421312e2..58d82f8b1 100644 --- a/network_io/win32/networkio.h +++ b/network_io/win32/networkio.h @@ -64,7 +64,7 @@ struct ap_socket_t { struct sockaddr_in *local_addr; struct sockaddr_in *remote_addr; size_t addr_len; - int timeout; + ap_interval_time_t timeout; }; struct ap_pollfd_t { diff --git a/network_io/win32/sendrecv.c b/network_io/win32/sendrecv.c index 409c200ec..33d39fb07 100644 --- a/network_io/win32/sendrecv.c +++ b/network_io/win32/sendrecv.c @@ -239,9 +239,11 @@ ap_status_t ap_sendfile(ap_socket_t * sock, ap_file_t * file, lasterror = WSAGetLastError(); if (lasterror == ERROR_IO_PENDING) { #ifdef WAIT_FOR_EVENT - rv = WaitForSingleObject(overlapped.hEvent, sock->timeout * 1000); + rv = WaitForSingleObject(overlapped.hEvent, + sock->timeout >= 0 ? sock->timeout / 1000 : INFINITE); #else - rv = WaitForSingleObject((HANDLE) sock->sock, sock->timeout * 1000); + rv = WaitForSingleObject((HANDLE) sock->sock, + sock->timeout >= 0 ? sock->timeout / 1000 : INFINITE); #endif if (rv == WAIT_OBJECT_0) lasterror = APR_SUCCESS; diff --git a/network_io/win32/sockopt.c b/network_io/win32/sockopt.c index d45e7b82e..d269b64e6 100644 --- a/network_io/win32/sockopt.c +++ b/network_io/win32/sockopt.c @@ -91,8 +91,9 @@ ap_status_t ap_setsocketopt(ap_socket_t *sock, ap_int32_t opt, ap_int32_t on) one = 0; if (opt & APR_SO_TIMEOUT) { - int timeout = on * 1000; /* Windows needs timeout in mSeconds */ - sock->timeout = timeout; + int timeout; + sock->timeout = on; + timeout = on / 1000; /* Windows needs timeout in mSeconds */ if (setsockopt(sock->sock, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout, sizeof(timeout)) == SOCKET_ERROR) { return WSAGetLastError(); diff --git a/test/ab_apr.c b/test/ab_apr.c index 7d36bbca4..f61773675 100644 --- a/test/ab_apr.c +++ b/test/ab_apr.c @@ -160,7 +160,7 @@ char *postdata; /* *buffer containing data from postfile */ ap_ssize_t postlen = 0; /* length of data to be POSTed */ char content_type[1024]; /* content type to put in POST header */ int port = 80; /* port number */ -time_t aprtimeout = 30000; /* timeout value... */ +time_t aprtimeout = 30 * AP_USEC_PER_SEC; /* timeout value... */ int use_html = 0; /* use html in the report */ char *tablestring; @@ -218,7 +218,7 @@ static void write_request(struct connection *c) { ap_ssize_t len = reqlen; c->connect = ap_now(); - ap_setsocketopt(c->aprsock, APR_SO_TIMEOUT, 30); + ap_setsocketopt(c->aprsock, APR_SO_TIMEOUT, 30 * AP_USEC_PER_SEC); if (ap_send(c->aprsock, request, &reqlen) != APR_SUCCESS && reqlen != len) { printf("Send request failed!\n"); diff --git a/test/client.c b/test/client.c index dfc2c80d1..cd78ce111 100644 --- a/test/client.c +++ b/test/client.c @@ -71,11 +71,17 @@ int main(int argc, char *argv[]) char *local_ipaddr, *remote_ipaddr; char *dest = "127.0.0.1"; ap_uint32_t local_port, remote_port; + ap_interval_time_t read_timeout = -1; + setbuf(stdout, NULL); if (argc > 1) { dest = argv[1]; } + if (argc > 2) { + read_timeout = AP_USEC_PER_SEC * atoi(argv[2]); + } + fprintf(stdout, "Initializing........."); if (ap_initialize() != APR_SUCCESS) { fprintf(stderr, "Something went wrong\n"); @@ -98,13 +104,15 @@ int main(int argc, char *argv[]) } fprintf(stdout, "OK\n"); - fprintf(stdout, "\tClient: Setting socket option NONBLOCK......."); - if (ap_setsocketopt(sock, APR_SO_NONBLOCK, 1) != APR_SUCCESS) { - ap_close_socket(sock); - fprintf(stderr, "Couldn't set socket option\n"); - exit(-1); + if (read_timeout == -1) { + fprintf(stdout, "\tClient: Setting socket option NONBLOCK......."); + if (ap_setsocketopt(sock, APR_SO_NONBLOCK, 1) != APR_SUCCESS) { + ap_close_socket(sock); + fprintf(stderr, "Couldn't set socket option\n"); + exit(-1); + } + fprintf(stdout, "OK\n"); } - fprintf(stdout, "OK\n"); fprintf(stdout, "\tClient: Setting port for socket......."); if (ap_set_remote_port(sock, 8021) != APR_SUCCESS) { @@ -143,11 +151,22 @@ int main(int argc, char *argv[]) } fprintf(stdout, "OK\n"); + if (read_timeout != -1) { + fprintf(stdout, "\tClient: Setting read timeout......."); + stat = ap_setsocketopt(sock, APR_SO_TIMEOUT, read_timeout); + if (stat) { + fprintf(stderr, "Problem setting timeout: %d\n", stat); + exit(-1); + } + fprintf(stdout, "OK\n"); + } + length = STRLEN; fprintf(stdout, "\tClient: Trying to receive data over socket......."); - if (ap_recv(sock, datarecv, &length) != APR_SUCCESS) { + + if ((stat = ap_recv(sock, datarecv, &length)) != APR_SUCCESS) { ap_close_socket(sock); - fprintf(stderr, "Problem receiving data\n"); + fprintf(stderr, "Problem receiving data: %d\n", stat); exit(-1); } if (strcmp(datarecv, "Recv data test")) { |