[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