stoddard 00/01/31 11:21:44
Modified: src/main http_protocol.c
src/lib/apr/network_io/win32 sendrecv.c
Log:
Set timeouts to sendfile operation in http_protocol.c. Fix bugs in Win32
sendfile implementation.
Revision Changes Path
1.53 +20 -10 apache-2.0/src/main/http_protocol.c
Index: http_protocol.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -r1.52 -r1.53
--- http_protocol.c 2000/01/28 18:01:16 1.52
+++ http_protocol.c 2000/01/31 19:21:37 1.53
@@ -963,9 +963,9 @@
#endif
ap_bsetopt(conn->client, BO_TIMEOUT,
- conn->keptalive
- ? &r->server->keep_alive_timeout
- : &r->server->timeout);
+ conn->keptalive
+ ? &r->server->keep_alive_timeout
+ : &r->server->timeout);
/* Get the request... */
if (!read_request_line(r)) {
@@ -2015,18 +2015,28 @@
*/
API_EXPORT(long) ap_send_fd(ap_file_t *fd, request_rec *r)
{
+ ap_status_t rv;
long len = r->finfo.size;
#ifdef HAVE_SENDFILE
if (!r->chunked) {
+ ap_bsetopt(r->connection->client, BO_TIMEOUT,
+ r->connection->keptalive
+ ? &r->server->keep_alive_timeout
+ : &r->server->timeout);
ap_bflush(r->connection->client);
- if (iol_sendfile(r->connection->client->iol,
- fd, /* The file to send */
- NULL, /* header and trailer iovecs */
- 0, /* Offset in file to begin sending from */
- &len,
- 0) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r,
+ rv = iol_sendfile(r->connection->client->iol,
+ fd, /* The file to send */
+ NULL, /* header and trailer iovecs */
+ 0, /* Offset in file to begin sending from */
+ &len,
+ 0);
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"ap_send_fd: iol_sendfile failed.");
+ }
+ if (r->connection->keptalive) {
+ ap_bsetopt(r->connection->client, BO_TIMEOUT,
+ &r->server->timeout);
}
}
else {
1.7 +42 -60 apache-2.0/src/lib/apr/network_io/win32/sendrecv.c
Index: sendrecv.c
===================================================================
RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/win32/sendrecv.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- sendrecv.c 2000/01/27 05:57:34 1.6
+++ sendrecv.c 2000/01/31 19:21:41 1.7
@@ -69,26 +69,13 @@
WSABUF wsaData;
int lasterror;
DWORD dwBytes = 0;
- int timeout = sock->timeout * 1000; /* Need timeout in milliseconds */
wsaData.len = *len;
wsaData.buf = (char*) buf;
- rv = setsockopt(sock->sock, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout,
- sizeof(timeout));
- if (rv == SOCKET_ERROR) {
- return WSAGetLastError();
- }
-
rv = WSASend(sock->sock, &wsaData, 1, &dwBytes, 0, NULL, NULL);
if (rv == SOCKET_ERROR) {
lasterror = WSAGetLastError();
- /* Test code: Remove before release */
- if (lasterror == WSAETIMEDOUT)
- printf("wsasend: Connection timed out\n");
- else
- printf("wsasend: connection failed. lasterror = %d\n",
lasterror);
-
return lasterror;
}
@@ -104,25 +91,13 @@
int lasterror;
DWORD dwBytes = 0;
DWORD flags = 0;
- int timeout = sock->timeout * 1000; /* Need timeout in milliseconds */
wsaData.len = *len;
wsaData.buf = (char*) buf;
- rv = setsockopt(sock->sock, SOL_SOCKET, SO_RCVTIMEO, (char*) &timeout,
- sizeof(timeout));
- if (rv == SOCKET_ERROR) {
- return WSAGetLastError();
- }
-
rv = WSARecv(sock->sock, &wsaData, 1, &dwBytes, &flags, NULL, NULL);
if (rv == SOCKET_ERROR) {
lasterror = WSAGetLastError();
- /* Test code: remove before release */
- if (lasterror == WSAETIMEDOUT)
- printf("wsarecv: Connection timed out\n");
- else
- printf("wsarecv: connection failed. lasterror = %d\n",
lasterror);
return lasterror;
}
@@ -137,7 +112,6 @@
int i;
int lasterror;
DWORD dwBytes = 0;
- int timeout = sock->timeout * 1000; /* Need timeout in milliseconds */
LPWSABUF pWsaData = (LPWSABUF) malloc(sizeof(WSABUF) * nvec);
@@ -149,25 +123,9 @@
pWsaData[i].len = vec[i].iov_len;
}
- rv = setsockopt(sock->sock, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout,
- sizeof(timeout));
- if (rv == SOCKET_ERROR) {
- lasterror = WSAGetLastError();
- /* Test code: remove before release */
- printf("win32_writev: setsockopt failed. errno = %d\n", lasterror);
- free(pWsaData);
- return lasterror;
- }
-
rv = WSASend(sock->sock, pWsaData, nvec, &dwBytes, 0, NULL, NULL);
if (rv == SOCKET_ERROR) {
lasterror = WSAGetLastError();
- /* Test code: remove before release */
- if (lasterror == WSAETIMEDOUT)
- printf("wsasend: Connection timed out\n");
- else
- printf("wsasend: connection failed. lasterror = %d\n",
lasterror);
-
free(pWsaData);
return lasterror;
}
@@ -194,17 +152,24 @@
ap_hdtr_t * hdtr, ap_off_t * offset, ap_size_t * len,
ap_int32_t flags)
{
+/*
+ *#define WAIT_FOR_EVENT
+ * Note: Waiting for the socket directly is much faster than creating a
seperate
+ * wait event. There are a couple of dangerous aspects to waiting directly
+ * for the socket. First, we should not wait on the socket if concurrent
threads
+ * can wait-on/signal the same socket. This shouldn't be happening with
Apache since
+ * a socket is uniquely tied to a thread. This will change when we begin
using
+ * async I/O with completion ports on the socket. Second, I am not sure how
the
+ * socket timeout code will work. I am hoping the socket will be signaled if
the
+ * setsockopt timeout expires. Need to verify this...
+ */
ap_ssize_t rv;
-#ifdef OVERLAPPED
OVERLAPPED overlapped;
-#endif
TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL;
- int i, lasterror, ptr = 0;
+ int i, ptr = 0;
+ int lasterror = APR_SUCCESS;
DWORD dwFlags = 0;
- int timeout = sock->timeout * 1000; /* Need timeout in milliseconds */
- rv = setsockopt(sock->sock, SOL_SOCKET, SO_SNDTIMEO,
- (char*) &timeout, sizeof(timeout));
#if 0
if (flags | APR_SENDFILE_KEEP_SOCKET)
dwFlags |= TF_REUSE_SOCKET;
@@ -215,7 +180,7 @@
#endif
/* TransmitFile can only send one header and one footer */
- memset(&tfb, '0', sizeof (tfb));
+ memset(&tfb, '\0', sizeof (tfb));
if (hdtr && hdtr->numheaders) {
ptfb = &tfb;
for (i = 0; i < hdtr->numheaders; i++) {
@@ -243,27 +208,44 @@
hdtr->trailers[i].iov_len);
ptr += hdtr->trailers[i].iov_len;
}
+ }
+ /* Initialize the overlapped structure */
+ memset(&overlapped,'\0', sizeof(overlapped));
+ if (offset && *offset) {
+ overlapped.Offset = *offset;
}
-#ifdef OVERLAPPED
- memset(&overlapped,'0', sizeof(overlapped));
+#ifdef WAIT_FOR_EVENT
+ overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
#endif
+
rv = TransmitFile(sock->sock, /* socket */
file->filehand, /* open file descriptor of the file to
be sent */
*len, /* number of bytes to send. 0=send all
*/
0, /* Number of bytes per send. 0=use
default */
-#ifdef OVERLAPPED
- &overlapped,
-#else
- NULL, /* OVERLAPPED structure */
-#endif
+ &overlapped, /* OVERLAPPED structure */
ptfb, /* header and trailer buffers */
dwFlags); /* flags to control various aspects of
TransmitFile */
if (!rv) {
lasterror = WSAGetLastError();
- printf("TransmitFile failed with error %d\n", lasterror);
- return lasterror;
+ if (lasterror == ERROR_IO_PENDING) {
+#ifdef WAIT_FOR_EVENT
+ rv = WaitForSingleObject(overlapped.hEvent, sock->timeout *
1000);
+#else
+ rv = WaitForSingleObject((HANDLE) sock->sock, sock->timeout *
1000);
+#endif
+ if (rv == WAIT_OBJECT_0)
+ lasterror = APR_SUCCESS;
+ else if (rv == WAIT_TIMEOUT)
+ lasterror = WAIT_TIMEOUT;
+ else if (rv == WAIT_ABANDONED)
+ lasterror = WAIT_ABANDONED;
+ else
+ lasterror = GetLastError();
+ }
}
-
- return APR_SUCCESS;
+#ifdef WAIT_FOR_EVENT
+ CloseHandle(overlapped.hEvent);
+#endif
+ return lasterror;
}
#endif