[prev in list] [next in list] [prev in thread] [next in thread] 

List:       apr-dev
Subject:    [PATCH] Win32 fix for corrupted byterange reply
From:       Bill Stoddard <bill () wstoddard ! com>
Date:       2004-05-28 13:16:24
Message-ID: 40B73BA8.9040800 () wstoddard ! com
[Download RAW message or body]

Failure scenario:
default_handler opens a pdf file to be sent via apr_sendfile (in other words, the \
file is opened for  overlapped i/o aka APR_XTHREAD).

An output filter is loaded (SSL in this case) that prevents apr_sendfile() from being \
used so we need to call  apr_file_read() to read the file contents into a bucket. \
When a windows file is opened for overlapped i/o, the  user application (APR in this \
case) must explicitly maintain the file pointer. The bug is that there is an  edge \
case where APR does not properly maintain the file pointer. If apr_file_seek() is \
called on a file opened  for overlapped i/o -before- apr_file_read(), the filepointer \
(maintained in apr_file_t) will not be properly  updated to the value passed in on \
apr_file_seek(). The subsequent apr_file_read() will read beginning at the  wrong \
offset and the pdf file will not be properly rendered.

There are two pieces to this fix. The key piece is here:
Index: seek.c
===================================================================
RCS file: /cvs/phoenix/2.0.47/srclib/apr/file_io/win32/seek.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 seek.c
--- seek.c    29 Jul 2003 20:19:26 -0000    1.1.1.1
+++ seek.c    27 May 2004 18:07:18 -0000
@@ -122,7 +122,10 @@
          *offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
          return rc;
      }
-    else if (thefile->pOverlapped) {
+    /* A file opened with APR_XTHREAD has been opened for overlapped i/o.
+     * APR must explicitly track the file pointer in this case.
+     */
+    else if (thefile->flags & APR_XTHREAD) {
          switch(where) {
              case APR_SET:
                  thefile->filePtr = *offset;

This change will cause the filepointer (thfile->filePtr) to be properly set on the \
first apr_file_seek(). This   single change will enable the file to be served up \
correctly.

A secondary issue I'd like to address is when the overlapped structure is created. \
Prior to this patch, the  overlapped structure (thefile->pOverlapped) was created in \
either apr_file_read() or apr_file_write(). The  following two changes move the \
creation of pOverlapped to apr_file_open().  Anyone see any problems with this?

Index: open.c
===================================================================
RCS file: /cvs/phoenix/2.0.47/srclib/apr/file_io/win32/open.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 open.c
--- open.c    29 Jul 2003 20:19:26 -0000    1.1.1.1
+++ open.c    27 May 2004 18:07:18 -0000
@@ -437,6 +437,23 @@
          apr_pool_cleanup_register((*new)->pool, (void *)(*new), file_cleanup,
                                    apr_pool_cleanup_null);
      }
+
+    /* Create the overlapped structure if the file is opened for overlapped
+     * i/o. Files opened for APR_XTHREAD support should always be opened for
+     * overlapped i/o and all files opened for overlapped i/o should be marked
+     * as APR_XTHREAD files. Note: Threads should not share an apr_file_t or
+     * its hEvent.
+     */
+    if ((*new)->flags & APR_XTHREAD) {
+        (*new)->pOverlapped = (OVERLAPPED*) apr_pcalloc((*new)->pool,
+                                                        sizeof(OVERLAPPED));
+        (*new)->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+        if (!(*new)->pOverlapped->hEvent) {
+            rv = apr_get_os_error();
+            return rv;
+        }
+    }
+
      return APR_SUCCESS;
  }

Index: readwrite.c
===================================================================
RCS file: /cvs/phoenix/2.0.47/srclib/apr/file_io/win32/readwrite.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 readwrite.c
--- readwrite.c    29 Jul 2003 20:19:26 -0000    1.1.1.1
+++ readwrite.c    27 May 2004 18:07:18 -0000
@@ -168,20 +168,6 @@
          return APR_SUCCESS;
      }

-    /* If the file is open for xthread support, allocate and
-     * initialize the overlapped and io completion event (hEvent).
-     * Threads should NOT share an apr_file_t or its hEvent.
-     */
-    if ((thefile->flags & APR_XTHREAD) && !thefile->pOverlapped ) {
-        thefile->pOverlapped = (OVERLAPPED*) apr_pcalloc(thefile->pool,
-                                                         sizeof(OVERLAPPED));
-        thefile->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-        if (!thefile->pOverlapped->hEvent) {
-            rv = apr_get_os_error();
-            return rv;
-        }
-    }
-
      /* Handle the ungetchar if there is one */
      if (thefile->ungetchar != -1) {
          bytes_read = 1;
@@ -252,20 +238,6 @@
  {
      apr_status_t rv;
      DWORD bwrote;
-
-    /* If the file is open for xthread support, allocate and
-     * initialize the overlapped and io completion event (hEvent).
-     * Threads should NOT share an apr_file_t or its hEvent.
-     */
-    if ((thefile->flags & APR_XTHREAD) && !thefile->pOverlapped ) {
-        thefile->pOverlapped = (OVERLAPPED*) apr_pcalloc(thefile->pool,
-                                                         sizeof(OVERLAPPED));
-        thefile->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-        if (!thefile->pOverlapped->hEvent) {
-            rv = apr_get_os_error();
-            return rv;
-        }
-    }

      if (thefile->buffered) {
          char *pos = (char *)buf;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic