Christian Grothoff 9 ani în urmă
părinte
comite
53e25ec3e4
4 a modificat fișierele cu 111 adăugiri și 7 ștergeri
  1. 4 0
      ChangeLog
  2. 1 1
      configure.ac
  3. 21 1
      src/microhttpd/mhd_itc.c
  4. 85 5
      src/microhttpd/mhd_itc.h

+ 4 - 0
ChangeLog

@@ -1,3 +1,7 @@
+Thu Sep 22 17:51:04 CEST 2016
+	Implementing support for eventfd() instead of pipe() for
+	signaling (on platforms that support it); fixing #3557. -CG
+
 Thu Sep 22 11:03:43 CEST 2016
 	Simplify internal error handling logic by folding it into the
 	MHD_socket_close_, MHD_mutex_lock_, MHD_mutex_unlock_ and

+ 1 - 1
configure.ac

@@ -562,7 +562,7 @@ AC_CHECK_HEADERS([sys/types.h sys/time.h sys/msg.h time.h sys/mman.h search.h sy
   sys/socket.h sys/select.h netdb.h netinet/in.h netinet/ip.h netinet/tcp.h arpa/inet.h \
   endian.h machine/endian.h sys/endian.h sys/param.h sys/machine.h sys/byteorder.h machine/param.h sys/isa_defs.h \
   inttypes.h stddef.h unistd.h \
-  sockLib.h inetLib.h net/if.h])
+  sockLib.h inetLib.h net/if.h sys/eventfd.h])
 AM_CONDITIONAL([HAVE_TSEARCH], [test "x$ac_cv_header_search_h" = "xyes"])
 
 # Check for generic functions

+ 21 - 1
src/microhttpd/mhd_itc.c

@@ -25,11 +25,30 @@
  */
 
 #include "mhd_itc.h"
-
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif /* HAVE_UNISTD_H */
 #include <fcntl.h>
+#include "internal.h"
+
+
+#ifdef HAVE_SYS_EVENTFD_H
+
+int
+MHD_pipe_write_ (struct MHD_Pipe pip,
+                 const void *ptr,
+                 size_t sz)
+{
+  uint64_t val = 1;
+  if (sizeof (val) !=
+      write (pip.event_fd,
+             &val,
+             sizeof (val)))
+    MHD_PANIC (_("Failed to write to eventfd\n"));
+  return sz;
+}
+
+#else
 
 #ifndef MHD_DONT_USE_PIPES
 #if !defined(_WIN32) || defined(__CYGWIN__)
@@ -65,3 +84,4 @@ MHD_itc_nonblocking_ (struct MHD_Pipe pip)
 }
 #endif /* _WIN32 && ! __CYGWIN__ */
 #endif /* ! MHD_DONT_USE_PIPES */
+#endif /* ! HAVE_SYS_EVENTFD_H */

+ 85 - 5
src/microhttpd/mhd_itc.h

@@ -19,9 +19,10 @@
 */
 
 /**
- * @file microhttpd/mhd_sockets.c
- * @brief  Header for platform-independent inter-thread communication
+ * @file microhttpd/mhd_itc.h
+ * @brief  Header for platform-independent inter-thread signaling via pipes
  * @author Karlson2k (Evgeny Grin)
+ * @author Christian Grothoff
  *
  * Provides basic abstraction for inter-thread communication.
  * Any functions can be implemented as macro on some platforms
@@ -29,17 +30,95 @@
  * Any function argument can be skipped in macro, so avoid
  * variable modification in function parameters.
  */
-
 #ifndef MHD_ITC_H
 #define MHD_ITC_H 1
 #include "mhd_options.h"
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <fcntl.h>
+
+#ifdef HAVE_SYS_EVENTFD_H
+
+#include <sys/eventfd.h>
+/* **************** Optimized eventfd PIPE implementation ********** */
+
+/**
+ * Data type for a MHD pipe.
+ */
+struct MHD_Pipe
+{
+  int event_fd;
+};
+
+/**
+ * create pipe
+ */
+#define MHD_pipe_(pip) ((-1 == (pip.event_fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK))) ? 0 : !0)
+
+/***
+ * Get description string of last errno for pipe operations.
+ */
+#define MHD_pipe_last_strerror_() strerror(errno)
+
+/**
+ * write data to real pipe
+ */
+int
+MHD_pipe_write_ (struct MHD_Pipe pip,
+                 const void *ptr,
+                 size_t sz);
+
+#define MHD_pipe_get_read_fd_(pip) (pip.event_fd)
+
+#define MHD_pipe_get_write_fd_(pip) (pip.event_fd)
+
+/**
+ * drain data from real pipe
+ */
+#define MHD_pipe_drain_(pip) do { \
+   uint64_t tmp; \
+   read (pip.event_fd, &tmp, sizeof (tmp)); \
+ } while (0)
+
+/**
+ * Close any FDs of the pipe (non-W32)
+ */
+#define MHD_pipe_close_(pip) do { \
+  close (pip.event_fd); \
+  } while (0)
+
+/**
+ * Check if we have an uninitialized pipe
+ */
+#define MHD_INVALID_PIPE_(pip)  (-1 == pip.event_fd)
+
+/**
+ * Setup uninitialized @a pip data structure.
+ */
+#define MHD_make_invalid_pipe_(pip) do { \
+    pip.event_fd = -1;        \
+  } while (0)
+
+
+/**
+ * Change itc FD options to be non-blocking.  As we already did this
+ * on eventfd creation, this always succeeds.
+ *
+ * @param fd the FD to manipulate
+ * @return non-zero if succeeded, zero otherwise
+ */
+#define MHD_itc_nonblocking_(pip) (!0)
+
+
+#else
+
 /* Force don't use pipes on W32 */
 #if defined(_WIN32) && !defined(MHD_DONT_USE_PIPES)
 #define MHD_DONT_USE_PIPES 1
 #endif /* defined(_WIN32) && !defined(MHD_DONT_USE_PIPES) */
 
-
 #ifndef MHD_DONT_USE_PIPES
 
 /* **************** STANDARD UNIX PIPE implementation ********** */
@@ -71,6 +150,7 @@ struct MHD_Pipe
  */
 #define MHD_pipe_write_(pip, ptr, sz) write((pip.fd[1]), (const void*)(ptr), (sz))
 
+
 #define MHD_pipe_get_read_fd_(pip) (pip.fd[0])
 
 #define MHD_pipe_get_write_fd_(pip) (pip.fd[1])
@@ -182,6 +262,6 @@ struct MHD_Pipe
 
 #endif /* MHD_DONT_USE_PIPES */
 
-
+#endif /* HAVE_SYS_EVENTFD_H */
 
 #endif /* MHD_ITC_H */