summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstoddard <stoddard@13f79535-47bb-0310-9956-ffa450edef68>2004-07-21 21:32:54 +0000
committerstoddard <stoddard@13f79535-47bb-0310-9956-ffa450edef68>2004-07-21 21:32:54 +0000
commitf15b29348c21f62fc310bd8359845d81410a45f5 (patch)
treef30fff45c97a5ae0e26b45b2cff2d11f546e563a
parent9a4ec7cef78bfa33c8f41c1e07597bc763e1de4f (diff)
downloadlibapr-f15b29348c21f62fc310bd8359845d81410a45f5.tar.gz
Win32: Fix bug in apr_socket_sendfile that interferred with LSPs. PR: 23982
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/branches/APR_0_9_BRANCH@65287 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES3
-rw-r--r--include/arch/win32/apr_arch_networkio.h5
-rw-r--r--network_io/win32/sendrecv.c49
-rw-r--r--network_io/win32/sockets.c4
4 files changed, 30 insertions, 31 deletions
diff --git a/CHANGES b/CHANGES
index f08020a7d..80f8ce528 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,7 @@
Changes with APR 0.9.5
+ *) Win32: Fix bug in apr_socket_sendfile that interferred with
+ Win32 LSPs. Bug is described in Apache 2.0 bugzilla report
+ 23982 [Jan Bilek, Bill Stoddard]
*) apr_proc_create() on Unix: Remove unnecessary check for read
access to the working directory of the child process.
diff --git a/include/arch/win32/apr_arch_networkio.h b/include/arch/win32/apr_arch_networkio.h
index b908e36e3..015be8d3c 100644
--- a/include/arch/win32/apr_arch_networkio.h
+++ b/include/arch/win32/apr_arch_networkio.h
@@ -41,6 +41,11 @@ struct apr_socket_t {
int remote_addr_unknown;
apr_int32_t netmask;
apr_int32_t inherit;
+ /* As of 07.20.04, the overlapped structure is only used by
+ * apr_socket_sendfile and that's where it will be allocated
+ * and initialized.
+ */
+ OVERLAPPED *overlapped;
sock_userdata_t *userdata;
};
diff --git a/network_io/win32/sendrecv.c b/network_io/win32/sendrecv.c
index f36c28c50..23ecea6b6 100644
--- a/network_io/win32/sendrecv.c
+++ b/network_io/win32/sendrecv.c
@@ -206,16 +206,6 @@ static apr_status_t collapse_iovec(char **off, apr_size_t *len,
#if APR_HAS_SENDFILE
/*
- *#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.
- */
-
-/*
* apr_status_t apr_socket_sendfile(apr_socket_t *, apr_file_t *, apr_hdtr_t *,
* apr_off_t *, apr_size_t *, apr_int32_t flags)
* Send a file from an open file descriptor to a socket, along with
@@ -239,13 +229,11 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock,
apr_off_t curoff = *offset;
DWORD dwFlags = 0;
DWORD nbytes;
- OVERLAPPED overlapped;
TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL;
int ptr = 0;
int bytes_to_send; /* Bytes to send out of the file (not including headers) */
int disconnected = 0;
int sendv_trailers = 0;
- HANDLE wait_event;
char hdtrbuf[4096];
if (apr_os_level < APR_WIN_NT) {
@@ -275,15 +263,7 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock,
return APR_SUCCESS;
}
- /* Initialize the header/trailer and overlapped structures */
memset(&tfb, '\0', sizeof (tfb));
- memset(&overlapped,'\0', sizeof(overlapped));
-#ifdef WAIT_FOR_EVENT
- wait_event = overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-#else
- wait_event = (HANDLE) sock->socketdes;
-#endif
-
/* Collapse the headers into a single buffer */
if (hdtr && hdtr->numheaders) {
ptfb = &tfb;
@@ -301,6 +281,12 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock,
}
}
+ /* Initialize the overlapped structure used on TransmitFile
+ */
+ if (!sock->overlapped) {
+ sock->overlapped = apr_pcalloc(sock->cntxt, sizeof(OVERLAPPED));
+ sock->overlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ }
while (bytes_to_send) {
if (bytes_to_send > MAX_SEGMENT_SIZE) {
nbytes = MAX_SEGMENT_SIZE;
@@ -329,16 +315,16 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock,
}
}
- overlapped.Offset = (DWORD)(curoff);
+ sock->overlapped->Offset = (DWORD)(curoff);
#if APR_HAS_LARGE_FILES
- overlapped.OffsetHigh = (DWORD)(curoff >> 32);
+ sock->overlapped->OffsetHigh = (DWORD)(curoff >> 32);
#endif
/* XXX BoundsChecker claims dwFlags must not be zero. */
rv = TransmitFile(sock->socketdes, /* socket */
file->filehand, /* open file descriptor of the file to be sent */
nbytes, /* number of bytes to send. 0=send all */
0, /* Number of bytes per send. 0=use default */
- &overlapped, /* OVERLAPPED structure */
+ sock->overlapped, /* OVERLAPPED structure */
ptfb, /* header and trailer buffers */
dwFlags); /* flags to control various aspects of TransmitFile */
if (!rv) {
@@ -346,17 +332,21 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock,
if ((status == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) ||
(status == APR_FROM_OS_ERROR(WSA_IO_PENDING)))
{
- rv = WaitForSingleObject(wait_event,
+ rv = WaitForSingleObject(sock->overlapped->hEvent,
(DWORD)(sock->timeout >= 0
? sock->timeout_ms : INFINITE));
if (rv == WAIT_OBJECT_0) {
status = APR_SUCCESS;
if (!disconnected) {
- if (!GetOverlappedResult(wait_event, &overlapped,
- &nbytes, FALSE)) {
- status = apr_get_os_error();
+ if (!WSAGetOverlappedResult(sock->socketdes,
+ sock->overlapped,
+ &nbytes,
+ FALSE,
+ &dwFlags)) {
+ status = apr_get_netos_error();
}
- /* Ugly code alert: GetOverlappedResult returns
+
+ /* Ugly code alert: WSAGetOverlappedResult returns
* a count of all bytes sent. This loop only
* tracks bytes sent out of the file.
*/
@@ -415,9 +405,6 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock,
}
}
-#ifdef WAIT_FOR_EVENT
- CloseHandle(overlapped.hEvent);
-#endif
return status;
}
diff --git a/network_io/win32/sockets.c b/network_io/win32/sockets.c
index 30c775339..82d16860b 100644
--- a/network_io/win32/sockets.c
+++ b/network_io/win32/sockets.c
@@ -35,6 +35,10 @@ static apr_status_t socket_cleanup(void *sock)
}
thesocket->socketdes = INVALID_SOCKET;
}
+ if (thesocket->overlapped) {
+ CloseHandle(thesocket->overlapped->hEvent);
+ thesocket->overlapped = NULL;
+ }
return APR_SUCCESS;
}