gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [libmicrohttpd] 02/03: Fixed thread safety with responses w


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] 02/03: Fixed thread safety with responses with same file FD, added enum value MHD_FEATURE_RESPONSES_SHARED_FD
Date: Thu, 01 Dec 2016 15:42:36 +0100

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a commit to branch master
in repository libmicrohttpd.

commit 7f9b98e25631731afd8b853b9f0163dc793a0a57
Author: Evgeny Grin (Karlson2k) <address@hidden>
AuthorDate: Sun Nov 27 23:15:49 2016 +0300

    Fixed thread safety with responses with same file FD,
    added enum value MHD_FEATURE_RESPONSES_SHARED_FD
---
 configure.ac              |  2 +-
 src/include/microhttpd.h  | 15 ++++++++++-
 src/microhttpd/daemon.c   | 12 ++++++++-
 src/microhttpd/response.c | 63 ++++++++++++++++++++++++++++++++---------------
 4 files changed, 69 insertions(+), 23 deletions(-)

diff --git a/configure.ac b/configure.ac
index 6c04181..d9316ab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1043,7 +1043,7 @@ AM_CONDITIONAL([HAVE_MAGIC], [[test 
"x$mhd_have_magic_open" = "xyes"]])
 # large file support (> 4 GB)
 AC_SYS_LARGEFILE
 AC_FUNC_FSEEKO
-AC_CHECK_FUNCS([_lseeki64 lseek64 sendfile64])
+AC_CHECK_FUNCS([lseek64 sendfile64 pread64 pread])
 
 # optional: have error messages ?
 AC_MSG_CHECKING([[whether to generate error messages]])
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index b72173e..32bf41b 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -2952,7 +2952,20 @@ enum MHD_FEATURE
    * If supported then #MHD_ALLOW_UPGRADE, #MHD_upgrade_action() and
    * #MHD_create_response_for_upgrade() can be used.
    */
-  MHD_FEATURE_UPGRADE = 17
+  MHD_FEATURE_UPGRADE = 17,
+
+  /**
+   * Get whether it's safe to use same FD for multiple calls of
+   * #MHD_create_response_from_fd() and whether it's safe to use single
+   * response generated by #MHD_create_response_from_fd() with multiple
+   * connections at same time.
+   * If #MHD_is_feature_supported() return #MHD_NO for this feature then
+   * usage of responses with same file FD in multiple parallel threads may
+   * results in incorrect data sent to remote client.
+   * It's always safe to use same file FD in multiple responses if MHD
+   * is run in any single thread mode.
+   */
+  MHD_FEATURE_RESPONSES_SHARED_FD = 18
 };
 
 
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 1b0a42b..97640ba 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -6018,7 +6018,11 @@ MHD_is_feature_supported(enum MHD_FEATURE feature)
       return MHD_NO;
 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
     case MHD_FEATURE_LARGE_FILE:
-#if defined(HAVE___LSEEKI64) || defined(HAVE_LSEEK64)
+#if defined(HAVE_PREAD64) || defined(_WIN32)
+      return MHD_YES;
+#elif defined(HAVE_PREAD)
+      return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
+#elif defined(HAVE_LSEEK64)
       return MHD_YES;
 #else
       return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
@@ -6035,6 +6039,12 @@ MHD_is_feature_supported(enum MHD_FEATURE feature)
 #else
       return MHD_NO;
 #endif
+    case MHD_FEATURE_RESPONSES_SHARED_FD:
+#if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
+      return MHD_YES;
+#else
+      return MHD_NO;
+#endif
     }
   return MHD_NO;
 }
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 8b89c5f..ad52f80 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -30,6 +30,9 @@
 #ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
 #endif /* HAVE_SYS_IOCTL_H */
+#ifdef _WIN32
+#include <windows.h>
+#endif /* _WIN32 */
 
 #include "internal.h"
 #include "response.h"
@@ -341,23 +344,35 @@ file_reader (void *cls,
              size_t max)
 {
   struct MHD_Response *response = cls;
+#ifndef _WIN32
   ssize_t n;
+#else  /* _WIN32 */
+  const HANDLE fh = (HANDLE) _get_osfhandle (response->fd);
+#endif /* _WIN32 */
   const int64_t offset64 = (int64_t)(pos + response->fd_off);
 
   if (offset64 < 0)
     return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is 
not possible */
 
+#ifndef _WIN32
+  if (max > SSIZE_MAX)
+    max = SSIZE_MAX; /* Clamp to maximum return value. */
+
+#if defined(HAVE_PREAD64)
+  n = pread64(response->fd, buf, max, offset64);
+#elif defined(HAVE_PREAD)
+  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
+       (offset64 > (uint64_t)INT32_MAX) )
+    return MHD_CONTENT_READER_END_WITH_ERROR; /* Read at required position is 
not possible. */
+
+  n = pread(response->fd, buf, max, (off_t) offset64);
+#else  /* ! HAVE_PREAD */
 #if defined(HAVE_LSEEK64)
   if (lseek64 (response->fd,
                offset64,
                SEEK_SET) != offset64)
     return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required 
position */
-#elif defined(HAVE___LSEEKI64)
-  if (_lseeki64 (response->fd,
-                 offset64,
-                 SEEK_SET) != offset64)
-    return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required 
position */
-#else /* !HAVE___LSEEKI64 */
+#else  /* ! HAVE_LSEEK64 */
   if ( (sizeof(off_t) < sizeof (uint64_t)) &&
        (offset64 > (uint64_t)INT32_MAX) )
     return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is 
not possible */
@@ -366,29 +381,37 @@ file_reader (void *cls,
              (off_t) offset64,
              SEEK_SET) != (off_t) offset64)
     return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required 
position */
-#endif
-
-#ifndef _WIN32
-  if (max > SSIZE_MAX)
-    max = SSIZE_MAX;
-
+#endif /* ! HAVE_LSEEK64 */
   n = read (response->fd,
             buf,
             max);
-#else  /* _WIN32 */
-  if (max > INT32_MAX)
-    max = INT32_MAX;
-
-  n = read (response->fd,
-            buf,
-            (unsigned int) max);
-#endif /* _WIN32 */
 
+#endif /* ! HAVE_PREAD */
   if (0 == n)
     return MHD_CONTENT_READER_END_OF_STREAM;
   if (n < 0)
     return MHD_CONTENT_READER_END_WITH_ERROR;
   return n;
+#else /* _WIN32 */
+  if (INVALID_HANDLE_VALUE == fh)
+    return MHD_CONTENT_READER_END_WITH_ERROR; /* Value of 'response->fd' is 
not valid. */
+  else
+    {
+      OVERLAPPED f_ol = {0, 0, 0, 0}; /* Initialize to zero. */
+      ULARGE_INTEGER pos_uli;
+      DWORD toRead = (max > INT32_MAX) ? INT32_MAX : (DWORD) max;
+      DWORD resRead;
+
+      pos_uli.QuadPart = (uint64_t) offset64; /* Simple transformation 64bit 
-> 2x32bit. */
+      f_ol.Offset = pos_uli.LowPart;
+      f_ol.OffsetHigh = pos_uli.HighPart;
+      if (! ReadFile(fh, (void*)buf, toRead, &resRead, &f_ol))
+        return MHD_CONTENT_READER_END_WITH_ERROR; /* Read error. */
+      if (0 == resRead)
+        return MHD_CONTENT_READER_END_OF_STREAM;
+      return (ssize_t) resRead;
+    }
+#endif /* _WIN32 */
 }
 
 

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]