summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Trawick <trawick@apache.org>2000-04-16 16:59:39 +0000
committerJeff Trawick <trawick@apache.org>2000-04-16 16:59:39 +0000
commit30514c7907998dd5905ec8d1a8e51cee34aec331 (patch)
tree432707f2d6c9ec82808aa99a723495708970a476
parent8d7cc60c98970f66eccdc57ec29d10d855a099b7 (diff)
downloadapr-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.h6
-rw-r--r--include/arch/beos/networkio.h2
-rw-r--r--include/arch/os2/networkio.h2
-rw-r--r--include/arch/unix/networkio.h2
-rw-r--r--include/arch/win32/networkio.h2
-rw-r--r--network_io/beos/networkio.h2
-rw-r--r--network_io/beos/sendrecv.c24
-rw-r--r--network_io/os2/networkio.h2
-rw-r--r--network_io/os2/sendrecv.c6
-rw-r--r--network_io/unix/networkio.h2
-rw-r--r--network_io/unix/sendrecv.c51
-rw-r--r--network_io/win32/networkio.h2
-rw-r--r--network_io/win32/sendrecv.c6
-rw-r--r--network_io/win32/sockopt.c5
-rw-r--r--test/ab_apr.c4
-rw-r--r--test/client.c35
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")) {