gnunet-svn
[Top][All Lists]
Advanced

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

[libmicrohttpd2] branch master updated (2e6777f -> cdd4c1f)


From: Admin
Subject: [libmicrohttpd2] branch master updated (2e6777f -> cdd4c1f)
Date: Fri, 06 Jun 2025 16:01:08 +0200

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

karlson2k pushed a change to branch master
in repository libmicrohttpd2.

    from 2e6777f  Implemented perf_replies tool for benchmarking
     new 5917d37  Added missing includes for "mhd_assert.h", sorted some 
includes
     new 6429e7a  Unified debug macro checks
     new 0a3e9e3  mhd_response_check_frozen_freeze(): fixed assert
     new e95381a  Improved error reporting for the listen socket creation
     new 827e178  perf_replies: muted compiler warning
     new f35064f  mhd_stream_finish_req_serving(): minor simplification
     new 1653368  mhd_atomic_counter: fixed formatting, fixed single thread 
version build
     new c2489bd  configure: improved test for alignof() detection
     new 4fb2834  Added detection and used "externally_visible" function 
attribute
     new f1579ec  Implemented and used counters based on atomic variables
     new 427f400  Made zeroing of memory pool optional, other memory pool 
improvements
     new cdd4c1f  get_all_net_updates_by_epoll(): reduced the size of the data 
passed to the kernel

The 12 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 configure.ac                                       | 270 ++++++++++++++++++++-
 src/incl_priv/mhd_sys_options.h                    |  67 ++++-
 src/include/d_options.rec                          |   6 +
 src/include/microhttpd2.h                          |  36 +++
 src/include/microhttpd2_generated_daemon_options.h |  44 ++++
 src/include/microhttpd2_preamble.h.in              |  26 ++
 src/mhd2/Makefile.am                               |   2 +-
 src/mhd2/auth_digest.c                             |  44 ++--
 src/mhd2/conn_get_info.c                           |   1 +
 src/mhd2/daemon_add_conn.c                         |  14 +-
 src/mhd2/daemon_get_info.c                         |   1 +
 src/mhd2/daemon_options.h                          |   7 +
 src/mhd2/daemon_set_options.c                      |   3 +
 src/mhd2/daemon_start.c                            | 141 +++++++++--
 src/mhd2/dcc_action.c                              |   2 +
 src/mhd2/events_process.c                          |  31 ++-
 src/mhd2/{mhd_mempool.c => mempool_funcs.c}        | 265 ++++++++------------
 src/mhd2/{mhd_mempool.h => mempool_funcs.h}        |  63 +++--
 src/mhd2/mempool_types.h                           |  64 +++++
 src/mhd2/mhd_atomic_counter.h                      | 112 ++++++++-
 src/mhd2/mhd_daemon.h                              |   7 +
 src/mhd2/mhd_reply.h                               |   2 +-
 src/mhd2/respond_with_error.c                      |   2 +-
 src/mhd2/response_funcs.c                          |   9 +-
 src/mhd2/stream_funcs.c                            |   6 +-
 src/mhd2/stream_process_reply.c                    |   2 +-
 src/mhd2/stream_process_request.c                  |   2 +-
 src/tools/perf_replies.c                           |   6 +-
 28 files changed, 952 insertions(+), 283 deletions(-)
 rename src/mhd2/{mhd_mempool.c => mempool_funcs.c} (77%)
 rename src/mhd2/{mhd_mempool.h => mempool_funcs.h} (81%)
 create mode 100644 src/mhd2/mempool_types.h

diff --git a/configure.ac b/configure.ac
index ce9934f..ec449f0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1312,7 +1312,7 @@ MHD_CHECK_CC_CFLAG([-Werror=attributes],[CFLAGS_ac],
       ]
     )
     AS_VAR_IF([mhd_cv_cflag_werror_attr_works],["yes"],
-      [errattr_CFLAGS="-Werror=attributes"]
+      [errattr_CFLAGS="-Werror=attributes"],[errattr_CFLAGS=""]
     )
   ]
 )
@@ -1472,6 +1472,108 @@ AS_CASE([${mhd_cv_cc_kwd_fallthrough}],
 CFLAGS_ac="${save_CFLAGS_ac}"
 CFLAGS="${CFLAGS_ac} ${user_CFLAGS}"
 
+# Check for full support of atomic variables 
+AC_CACHE_CHECK([whether $CC supports atomic variables],
+  [mhd_cv_c_atomic_variables],
+  [
+    AC_COMPILE_IFELSE(
+      [
+        AC_LANG_SOURCE(
+          [[
+#include <stdatomic.h>
+
+#ifdef __STDC_NO_ATOMICS__
+#error __STDC_NO_ATOMICS__ is declared
+choke me now
+#endif
+
+int main(void)
+{
+  volatile _Atomic int atmc_var;
+  int natmc_var;
+
+  atomic_init(&atmc_var, 0);
+
+  if (0 == atomic_exchange_explicit(&atmc_var, 16, memory_order_relaxed))
+    atomic_store_explicit(&atmc_var, 7, memory_order_release);
+
+  natmc_var = atomic_fetch_add_explicit(&atmc_var, 15, memory_order_acq_rel);
+
+  natmc_var = atomic_fetch_sub_explicit(&atmc_var, natmc_var, 
memory_order_relaxed);
+
+  natmc_var = atomic_fetch_or_explicit(&atmc_var, natmc_var, 
memory_order_seq_cst);
+
+  natmc_var = atomic_fetch_and_explicit(&atmc_var, natmc_var, 
memory_order_relaxed);
+
+  natmc_var = atomic_fetch_xor_explicit(&atmc_var, natmc_var, 
memory_order_release);
+
+  return natmc_var + 1 - atomic_load_explicit(&atmc_var, memory_order_acquire);
+}
+          ]]
+        )
+      ],
+      [mhd_cv_c_atomic_variables="yes"],[mhd_cv_c_atomic_variables="no"]
+    )
+  ]
+)
+AS_VAR_IF([mhd_cv_c_atomic_variables],["yes"],
+  [
+    AC_DEFINE([MHD_SUPPORT_ATOMIC_VARIABLES],[1],[Define to 1 i][f atomic 
variables are fully supported])
+    AC_DEFINE([MHD_SUPPORT_ATOMIC_COUNTERS],[1],[Define to 1 i][f counter 
subset of atomic operations is supported])
+  ],
+  [
+    # Check for minimal atomic variables support
+    AC_CACHE_CHECK([whether $CC supports atomic counters],
+      [mhd_cv_c_atomic_counters],
+      [
+        AC_COMPILE_IFELSE(
+          [
+            AC_LANG_SOURCE(
+              [[
+#if defined(HAVE_STDDEF_H)
+#  include <stddef.h> /* size_t */
+#elif defined(HAVE_STDLIB_H)
+#  include <stdlib.h> /* should provide size_t */
+#else
+#  include <stdio.h> /* should provide size_t */
+#endif
+#ifdef HAVE_CRTDEFS_H
+#  include <crtdefs.h> /* W32-specific header */
+#endif
+
+#include <stdatomic.h>
+
+#ifdef __STDC_NO_ATOMICS__
+#error __STDC_NO_ATOMICS__ is declared
+choke me now
+#endif
+
+int main(void)
+{
+  volatile _Atomic size_t cntr;
+
+  atomic_init(&cntr, 0);
+
+  atomic_fetch_add_explicit(&cntr, 1, memory_order_relaxed);
+  atomic_fetch_sub_explicit(&cntr, 1, memory_order_release);
+
+  return
+    (0u == atomic_load_explicit(&cntr, memory_order_relaxed)) ?
+    0 : 2;
+}
+              ]]
+            )
+          ],
+          [mhd_cv_c_atomic_counters="yes"],[mhd_cv_c_atomic_counters="no"]
+        )
+      ]
+    )
+    AS_VAR_IF([mhd_cv_c_atomic_counters],["yes"],
+      [AC_DEFINE([MHD_SUPPORT_ATOMIC_COUNTERS],[1],[Define to 1 i][f counter 
subset of atomic operations is supported])]
+    )
+  ]
+)
+
 AC_CHECK_HEADERS([stdalign.h], [], [], [AC_INCLUDES_DEFAULT])
 AC_CACHE_CHECK([[for C11 'alignof()' support]], [[mhd_cv_c_alignof]],
   [AC_COMPILE_IFELSE(
@@ -1501,7 +1603,7 @@ AC_CACHE_CHECK([[for C11 'alignof()' support]], 
[[mhd_cv_c_alignof]],
 #endif
                        ]], [[
                          /* Should fail if 'alignof()' works */
-                         int var1[alignof(nonexisting_type) - 1];
+                         int var1[alignof(nonexisting_type)];
 
                          /* Mute compiler warnings */
                          var1[0] = 1;
@@ -4259,6 +4361,27 @@ int main(void) {return test_hidden_func();}
   ]
 )
 CFLAGS="${CFLAGS_ac} ${user_CFLAGS} ${errattr_CFLAGS}"
+AC_CACHE_CHECK([whether $CC supports __attribute__ 
((externally_visible))],[mhd_cv_cc_attr_extern_vis],
+  [
+    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+int test_func(void) __attribute__ ((externally_visible));
+__attribute__ ((externally_visible)) int
+test_func(void) {return 0; }
+
+int main(void) { return test_func(); }
+          ]])
+      ],
+      [mhd_cv_cc_attr_extern_vis="yes"],[mhd_cv_cc_attr_extern_vis="no"]
+    )
+  ]
+)
+AS_VAR_IF([mhd_cv_cc_attr_extern_vis],["yes"],
+  [
+    AC_DEFINE([HAVE_ATTR_EXTERN_VISIBLE],[1],
+      [Define to '1' if your compiler supports 
__attribute__((externally_visible))]
+    )
+  ]
+)
 AC_CACHE_CHECK([whether $CC supports __attribute__ 
((warn_unused_result))],[mhd_cv_cc_attr_warn_unused_res],
   [
     AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
@@ -4304,6 +4427,149 @@ AS_VAR_IF([mhd_cv_cc_attr_ret_nonnull],["yes"],
     )
   ]
 )
+AC_CACHE_CHECK([whether $CC supports __attribute__ ((assume_aligned 
(N)))],[mhd_cv_cc_attr_func_assume_aligned],
+  [
+    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+static __attribute__((assume_aligned (1))) void*
+test_func(void) {
+  static signed char c = 0;
+  return (void*) &c;
+}
+
+int main(void) {
+  return test_func() ? 0 : 1;
+}
+          ]])
+      ],
+      
[mhd_cv_cc_attr_func_assume_aligned="yes"],[mhd_cv_cc_attr_func_assume_aligned="no"]
+    )
+  ]
+)
+AS_VAR_IF([mhd_cv_cc_attr_func_assume_aligned],["yes"],
+  [
+    AC_DEFINE([HAVE_ATTR_FUNC_ASSUME_ALIGNED],[1],
+      [Define to '1' if your compiler supports 
__attribute__((assume_aligned(N)))]
+    )
+  ]
+)
+AC_CACHE_CHECK([whether $CC supports __attribute__ ((alloc_size 
(N)))],[mhd_cv_cc_attr_func_alloc_size],
+  [
+    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#if defined(HAVE_STDDEF_H)
+#  include <stddef.h> /* NULL */
+#else
+#  include <string.h> /* should provide NULL */
+#endif
+
+static __attribute__((alloc_size(1))) void*
+test_alloc(unsigned short size) {
+  static char buf_alloc[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+  static unsigned short allocated = 0;
+  void *ret;
+  if (sizeof(buf_alloc) - allocated < size)
+    return NULL;
+  ret = (void*) (buf_alloc + allocated);
+  allocated -= size;
+  return ret;
+}
+
+int main(void) {
+  return test_alloc(1) ? 0 : 1;
+}
+          ]])
+      ],
+      
[mhd_cv_cc_attr_func_alloc_size="yes"],[mhd_cv_cc_attr_func_alloc_size="no"]
+    )
+  ]
+)
+AS_VAR_IF([mhd_cv_cc_attr_func_alloc_size],["yes"],
+  [
+    AC_DEFINE([HAVE_ATTR_FUNC_ALLOC_SIZE],[1],
+      [Define to '1' if your compiler supports __attribute__((alloc_size(N)))]
+    )
+  ]
+)
+AC_CACHE_CHECK([whether $CC supports __attribute__ 
((malloc))],[mhd_cv_cc_attr_func_malloc],
+  [
+    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#if defined(HAVE_STDDEF_H)
+#  include <stddef.h> /* NULL */
+#else
+#  include <string.h> /* should provide NULL */
+#endif
+
+static __attribute__((malloc)) void*
+test_alloc(void) {
+  static char buf_alloc[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+  static int used_flag = 0;
+  if (used_flag)
+    return NULL;
+  used_flag = !0;
+  return buf_alloc;
+}
+
+int main(void) {
+  return test_alloc() ? 0 : 1;
+}
+          ]])
+      ],
+      [mhd_cv_cc_attr_func_malloc="yes"],[mhd_cv_cc_attr_func_malloc="no"]
+    )
+  ]
+)
+AS_VAR_IF([mhd_cv_cc_attr_func_malloc],["yes"],
+  [
+    AC_DEFINE([HAVE_ATTR_FUNC_MALLOC],[1],
+      [Define to '1' if your compiler supports __attribute__((malloc))]
+    )
+  ]
+)
+AC_CACHE_CHECK([whether $CC supports __attribute__ 
((malloc(deallocator)))],[mhd_cv_cc_attr_func_malloc_dealloc],
+  [
+    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#if defined(HAVE_STDDEF_H)
+#  include <stddef.h> /* NULL */
+#else
+#  include <string.h> /* should provide NULL */
+#endif
+
+static int used_flag = 0;
+static char buf_alloc[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+static void
+test_dealloc(void *ptr) {
+  if (! used_flag)
+    return;
+  if (ptr != (void*) buf_alloc)
+    return;
+  used_flag = 0;
+}
+
+static __attribute__((malloc(test_dealloc))) void*
+test_alloc(void) {
+  if (used_flag)
+    return NULL;
+  used_flag = !0;
+  return (void*) buf_alloc;
+}
+
+int main(void) {
+  test_dealloc(test_alloc());
+  return 0;
+}
+          ]])
+      ],
+      
[mhd_cv_cc_attr_func_malloc_dealloc="yes"],[mhd_cv_cc_attr_func_malloc_dealloc="no"]
+    )
+  ]
+)
+AS_VAR_IF([mhd_cv_cc_attr_func_malloc_dealloc],["yes"],
+  [
+    AC_DEFINE([HAVE_ATTR_FUNC_MALLOC_DEALLOC],[1],
+      [Define to '1' if your compiler supports 
__attribute__((malloc(deallocator)))]
+    )
+  ]
+)
 AC_CACHE_CHECK([whether $CC supports __attribute__ 
((nonnull))],[mhd_cv_cc_attr_nonnull],
   [
     AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
diff --git a/src/incl_priv/mhd_sys_options.h b/src/incl_priv/mhd_sys_options.h
index c79c312..a2b0fd4 100644
--- a/src/incl_priv/mhd_sys_options.h
+++ b/src/incl_priv/mhd_sys_options.h
@@ -35,9 +35,9 @@
 #define MHD_SYS_OPTIONS_H 1
 
 #ifndef HAVE_CONFIG_H
-#ifndef _MSC_VER
+#  ifndef _MSC_VER
 #error HAVE_CONFIG_H must be defined
-#endif
+#  endif
 #endif
 
 #include "mhd_config.h"
@@ -72,6 +72,13 @@
 #  define MHD_EXTERN_USED /* empty */
 #endif
 
+#if defined(HAVE_ATTR_EXTERN_VISIBLE) \
+  && (defined(PIC) || defined(DLL_EXPORT) || defined(MHD_W32DLL))
+#  define mhd_EXTERNALLY_ACCESSIBLE __attribute__ ((externally_visible))
+#else
+#  define mhd_EXTERNALLY_ACCESSIBLE /* empty */
+#endif
+
 #if defined(MHD_EXTERN_) && defined(BUILDING_MHD_LIB)
 #  undef MHD_EXTERN_
 #endif /* MHD_EXTERN_ && BUILDING_MHD_LIB */
@@ -80,7 +87,8 @@
 #  ifdef BUILDING_MHD_LIB
 /* Building MHD itself */
 #    define MHD_EXTERN_ \
-        extern MHD_VISIBILITY_EXTERN MHD_EXPORTED MHD_EXTERN_USED
+        extern MHD_VISIBILITY_EXTERN MHD_EXPORTED \
+        mhd_EXTERNALLY_ACCESSIBLE MHD_EXTERN_USED
 #  else  /* ! BUILDING_MHD_LIB */
 /* Test or example code, using MHD as a library */
 #    define MHD_EXTERN_ extern
@@ -212,6 +220,55 @@
 #  define MHD_FN_PAR_DYN_ARR_SIZE_(size)  1
 #endif
 
+#ifdef HAVE_ATTR_FUNC_ASSUME_ALIGNED
+#  define mhd_FN_RET_ALIGNED(align) __attribute__((assume_aligned(align)))
+#else
+#  define mhd_FN_RET_ALIGNED(align)     /* empty */
+#endif
+
+#ifdef HAVE_ATTR_FUNC_ALLOC_SIZE
+/**
+ * Indicates that returned pointer points to object with the size specified
+ * by parameter number @a param_num.
+ */
+#  define mhd_FN_RET_SIZED(param_num) __attribute__((alloc_size(param_num)))
+#else
+/**
+ * Indicates that returned pointer points to object with the size specified
+ * by parameter number @a param_num.
+ */
+#  define mhd_FN_RET_SIZED(align)       /* empty */
+#endif
+
+#ifdef HAVE_ATTR_FUNC_MALLOC
+/**
+ * Indicates that returned pointer is unique and does not alias any other
+ * pointers.
+ */
+#  define mhd_FN_RET_UNALIASED __attribute__((malloc))
+#else
+/**
+ * Indicates that returned pointer is unique and does not alias any other
+ * pointers.
+ */
+#  define mhd_FN_RET_UNALIASED          /* empty */
+#endif
+
+#ifdef HAVE_ATTR_FUNC_MALLOC_DEALLOC
+/**
+ * Indicates that function creates the object that mast be destructed by
+ * another function @a destructor.
+ */
+#  define mhd_FN_OBJ_CONSTRUCTOR(destructor) \
+          __attribute__((malloc(destructor)))
+#else
+/**
+ * Indicates that function creates the object that mast be destructed by
+ * another function @a destructor.
+ */
+  #  define mhd_FN_OBJ_CONSTRUCTOR(destructor)  /* empty */
+#endif
+
 #ifdef HAVE_ATTR_ENUM_EXTNS_CLOSED
 #  define MHD_FIXED_ENUM_ __attribute__((enum_extensibility (closed)))
 #else
@@ -507,7 +564,7 @@
 #  define mhd_SEND_SPIPE_SUPPRESS_NEEDED     1
 #endif
 
-#ifdef _DEBUG
+#ifndef NDEBUG
 #  ifndef MHD_NO_TLS_DEBUG_MESSAGES
 #    ifndef mhd_USE_TLS_DEBUG_MESSAGES
 /**
@@ -546,6 +603,8 @@
 #  define MHD_NORETURN_ __attribute__((__noreturn__))
 #  undef mhd_FALLTHROUGH
 #  define mhd_FALLTHROUGH ((void) 0)
+#  undef _Atomic
+#  define _Atomic /* empty */
 #endif
 
 /* Avoid interference with third-party headers */
diff --git a/src/include/d_options.rec b/src/include/d_options.rec
index 0d9c505..b3e5d6e 100644
--- a/src/include/d_options.rec
+++ b/src/include/d_options.rec
@@ -290,6 +290,12 @@ Description1: the accept policy callback
 Argument2: void *apc_cls
 Description2: the closure for the callback
 
+Name: CONN_BUFF_ZEROING
+Value: 164
+Comment: Set mode of connection memory buffer zeroing
+Argument1: enum MHD_ConnBufferZeroingMode buff_zeroing
+Description1: buffer zeroing mode
+
 # Requests processing
 
 Name: protocol_strict_level
diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h
index 1d068ff..ccefdd4 100644
--- a/src/include/microhttpd2.h
+++ b/src/include/microhttpd2.h
@@ -3535,6 +3535,32 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_UseStictLevel
   MHD_USL_NEAREST = 2
 };
 
+
+/**
+ * Connection memory buffer zeroing mode.
+ * Works as a hardening measure.
+ */
+enum MHD_FIXED_ENUM_APP_SET_ MHD_ConnBufferZeroingMode
+{
+  /**
+   * Do not perform zeroing of connection memory buffer.
+   * Default mode.
+   */
+  MHD_CONN_BUFFER_ZEROING_DISABLED = 0
+  ,
+  /**
+   * Perform connection memory buffer zeroing before processing request.
+   */
+  MHD_CONN_BUFFER_ZEROING_BASIC = 1
+  ,
+  /**
+   * Perform connection memory buffer zeroing before processing request and
+   * when reusing buffer memory areas during processing request.
+   */
+  MHD_CONN_BUFFER_ZEROING_HEAVY = 2
+};
+
+
 /* ********************** (d) TLS support ********************** */
 
 /**
@@ -4337,6 +4363,16 @@ MHD_D_OPTION_ACCEPT_POLICY (
   void *apc_cls
   );
 
+/**
+ * Set mode of connection memory buffer zeroing
+ * @param buff_zeroing buffer zeroing mode
+ * @return structure with the requested setting
+ */
+struct MHD_DaemonOptionAndValue
+MHD_D_OPTION_CONN_BUFF_ZEROING (
+  enum MHD_ConnBufferZeroingMode buff_zeroing
+  );
+
 /**
  * Set how strictly MHD will enforce the HTTP protocol.
  * @param sl the level of strictness
diff --git a/src/include/microhttpd2_generated_daemon_options.h 
b/src/include/microhttpd2_generated_daemon_options.h
index e498bb8..a257340 100644
--- a/src/include/microhttpd2_generated_daemon_options.h
+++ b/src/include/microhttpd2_generated_daemon_options.h
@@ -180,6 +180,12 @@ Works only when #MHD_D_OPTION_BIND_PORT() or 
#MHD_D_OPTION_BIND_SA() are used.
   MHD_D_O_ACCEPT_POLICY = 163
   ,
 
+  /**
+   * Set mode of connection memory buffer zeroing
+   */
+  MHD_D_O_CONN_BUFF_ZEROING = 164
+  ,
+
   /**
    * Set how strictly MHD will enforce the HTTP protocol.
    */
@@ -732,6 +738,12 @@ union MHD_DaemonOptionValue
    */
   struct MHD_DaemonOptionValueAcceptPol accept_policy;
 
+  /**
+   * Value for #MHD_D_O_CONN_BUFF_ZEROING.
+   * buffer zeroing mode
+   */
+  enum MHD_ConnBufferZeroingMode conn_buff_zeroing;
+
   /**
    * Value for #MHD_D_O_PROTOCOL_STRICT_LEVEL.
    * the level of strictness
@@ -1198,6 +1210,19 @@ Works only when #MHD_D_OPTION_BIND_PORT() or 
#MHD_D_OPTION_BIND_SA() are used.
           .val.accept_policy.v_apc_cls = (apc_cls) \
         } \
         MHD_RESTORE_WARN_COMPOUND_LITERALS_ MHD_RESTORE_WARN_AGGR_DYN_INIT_
+/**
+ * Set mode of connection memory buffer zeroing
+ * @param buff_zeroing buffer zeroing mode
+ * @return structure with the requested setting
+ */
+#  define MHD_D_OPTION_CONN_BUFF_ZEROING(buff_zeroing) \
+        MHD_NOWARN_COMPOUND_LITERALS_ MHD_NOWARN_AGGR_DYN_INIT_ \
+          (const struct MHD_DaemonOptionAndValue) \
+        { \
+          .opt = MHD_D_O_CONN_BUFF_ZEROING,  \
+          .val.conn_buff_zeroing = (buff_zeroing) \
+        } \
+        MHD_RESTORE_WARN_COMPOUND_LITERALS_ MHD_RESTORE_WARN_AGGR_DYN_INIT_
 /**
  * Set how strictly MHD will enforce the HTTP protocol.
  * @param sl the level of strictness
@@ -2000,6 +2025,25 @@ MHD_D_OPTION_ACCEPT_POLICY (
 }
 
 
+/**
+ * Set mode of connection memory buffer zeroing
+ * @param buff_zeroing buffer zeroing mode
+ * @return structure with the requested setting
+ */
+static MHD_INLINE struct MHD_DaemonOptionAndValue
+MHD_D_OPTION_CONN_BUFF_ZEROING (
+  enum MHD_ConnBufferZeroingMode buff_zeroing
+  )
+{
+  struct MHD_DaemonOptionAndValue opt_val;
+
+  opt_val.opt = MHD_D_O_CONN_BUFF_ZEROING;
+  opt_val.val.conn_buff_zeroing = buff_zeroing;
+
+  return opt_val;
+}
+
+
 /**
  * Set how strictly MHD will enforce the HTTP protocol.
  * @param sl the level of strictness
diff --git a/src/include/microhttpd2_preamble.h.in 
b/src/include/microhttpd2_preamble.h.in
index 61c40e5..3c4315e 100644
--- a/src/include/microhttpd2_preamble.h.in
+++ b/src/include/microhttpd2_preamble.h.in
@@ -3535,6 +3535,32 @@ enum MHD_FIXED_ENUM_APP_SET_ MHD_UseStictLevel
   MHD_USL_NEAREST = 2
 };
 
+
+/**
+ * Connection memory buffer zeroing mode.
+ * Works as a hardening measure.
+ */
+enum MHD_FIXED_ENUM_APP_SET_ MHD_ConnBufferZeroingMode
+{
+  /**
+   * Do not perform zeroing of connection memory buffer.
+   * Default mode.
+   */
+  MHD_CONN_BUFFER_ZEROING_DISABLED = 0
+  ,
+  /**
+   * Perform connection memory buffer zeroing before processing request.
+   */
+  MHD_CONN_BUFFER_ZEROING_BASIC = 1
+  ,
+  /**
+   * Perform connection memory buffer zeroing before processing request and
+   * when reusing buffer memory areas during processing request.
+   */
+  MHD_CONN_BUFFER_ZEROING_HEAVY = 2
+};
+
+
 /* ********************** (d) TLS support ********************** */
 
 /**
diff --git a/src/mhd2/Makefile.am b/src/mhd2/Makefile.am
index b835902..7be2b1b 100644
--- a/src/mhd2/Makefile.am
+++ b/src/mhd2/Makefile.am
@@ -58,7 +58,7 @@ libmicrohttpd2_la_SOURCES = \
   mhd_itc.c                 mhd_itc.h                 mhd_itc_types.h \
   mhd_threads.c             mhd_threads.h             sys_thread_entry_type.h \
   mhd_mono_clock.c          mhd_mono_clock.h \
-  mhd_mempool.c             mhd_mempool.h \
+  mempool_funcs.c           mempool_funcs.h           mempool_types.h \
   mhd_read_file.c           mhd_read_file.h \
   mhd_recv.c                mhd_recv.h \
   mhd_send.c                mhd_send.h \
diff --git a/src/mhd2/auth_digest.c b/src/mhd2/auth_digest.c
index 3c51309..b40f482 100644
--- a/src/mhd2/auth_digest.c
+++ b/src/mhd2/auth_digest.c
@@ -1430,12 +1430,12 @@ struct DigestAlgorithm
   /**
    * Buffer for hex-print of the final digest.
    */
-#ifdef _DEBUG
+#ifndef NDEBUG
   bool uninitialised; /**< The structure has been not set-up */
   bool algo_selected; /**< The algorithm has been selected */
   bool ready_for_hashing; /**< The structure is ready to hash data */
   bool hashing; /**< Some data has been hashed, but the digest has not 
finalised yet */
-#endif /* _DEBUG */
+#endif /* NDEBUG */
 };
 
 
@@ -1486,7 +1486,7 @@ digest_get_size (struct DigestAlgorithm *da)
 MHD_static_inline_ void
 digest_setup_zero (struct DigestAlgorithm *da)
 {
-#ifdef _DEBUG
+#ifndef NDEBUG
   da->uninitialised = false;
   da->algo_selected = false;
   da->ready_for_hashing = false;
@@ -1552,7 +1552,7 @@ MHD_static_inline_ MHD_FN_MUST_CHECK_RESULT_ 
MHD_FN_PAR_NONNULL_ALL_ bool
 digest_init_one_time (struct DigestAlgorithm *da,
                       enum MHD_DigestBaseAlgo algo)
 {
-#ifdef _DEBUG
+#ifndef NDEBUG
   da->uninitialised = false;
   da->algo_selected = false;
   da->ready_for_hashing = false;
@@ -1563,11 +1563,11 @@ digest_init_one_time (struct DigestAlgorithm *da,
   case MHD_DIGEST_BASE_ALGO_MD5:
 #ifdef MHD_SUPPORT_MD5
     da->algo = MHD_DIGEST_BASE_ALGO_MD5;
-#  ifdef _DEBUG
+#  ifndef NDEBUG
     da->algo_selected = true;
 #  endif
     mhd_MD5_init_one_time (&(da->ctx.md5_ctx));
-#  ifdef _DEBUG
+#  ifndef NDEBUG
     da->ready_for_hashing = true;
 #  endif
     return true;
@@ -1577,11 +1577,11 @@ digest_init_one_time (struct DigestAlgorithm *da,
   case MHD_DIGEST_BASE_ALGO_SHA256:
 #ifdef MHD_SUPPORT_SHA256
     da->algo = MHD_DIGEST_BASE_ALGO_SHA256;
-#  ifdef _DEBUG
+#  ifndef NDEBUG
     da->algo_selected = true;
 #  endif
     mhd_SHA256_init_one_time (&(da->ctx.sha256_ctx));
-#  ifdef _DEBUG
+#  ifndef NDEBUG
     da->ready_for_hashing = true;
 #  endif
     return true;
@@ -1591,11 +1591,11 @@ digest_init_one_time (struct DigestAlgorithm *da,
   case MHD_DIGEST_BASE_ALGO_SHA512_256:
 #ifdef MHD_SUPPORT_SHA512_256
     da->algo = MHD_DIGEST_BASE_ALGO_SHA512_256;
-#  ifdef _DEBUG
+#  ifndef NDEBUG
     da->algo_selected = true;
 #  endif
     mhd_SHA512_256_init_one_time (&(da->ctx.sha512_256_ctx));
-#  ifdef _DEBUG
+#  ifndef NDEBUG
     da->ready_for_hashing = true;
 #  endif
     return true;
@@ -1661,7 +1661,7 @@ digest_update (struct DigestAlgorithm *restrict da,
     mhd_UNREACHABLE ();
     break;
   }
-#ifdef _DEBUG
+#ifndef NDEBUG
   da->hashing = true;
 #endif
 }
@@ -1749,12 +1749,12 @@ digest_calc_hash (struct DigestAlgorithm *da,
 #ifdef MHD_SUPPORT_MD5
 #  ifdef mhd_MD5_HAS_FINISH
     mhd_MD5_finish (&da->ctx.md5_ctx, digest);
-#    ifdef _DEBUG
+#    ifndef NDEBUG
     da->ready_for_hashing = false;
 #    endif /* _DEBUG */
 #  else  /* ! mhd_MD5_HAS_FINISH */
     mhd_MD5_finish_reset (&da->ctx.md5_ctx, digest);
-#    ifdef _DEBUG
+#    ifndef NDEBUG
     da->ready_for_hashing = true;
 #    endif /* _DEBUG */
 #  endif /* ! mhd_MD5_HAS_FINISH */
@@ -1767,12 +1767,12 @@ digest_calc_hash (struct DigestAlgorithm *da,
 #ifdef MHD_SUPPORT_SHA256
 #  ifdef mhd_SHA256_HAS_FINISH
     mhd_SHA256_finish (&da->ctx.sha256_ctx, digest);
-#    ifdef _DEBUG
+#    ifndef NDEBUG
     da->ready_for_hashing = false;
 #    endif /* _DEBUG */
 #  else  /* ! mhd_SHA256_HAS_FINISH */
     mhd_SHA256_finish_reset (&da->ctx.sha256_ctx, digest);
-#    ifdef _DEBUG
+#    ifndef NDEBUG
     da->ready_for_hashing = true;
 #    endif /* _DEBUG */
 #  endif /* ! mhd_SHA256_HAS_FINISH */
@@ -1785,12 +1785,12 @@ digest_calc_hash (struct DigestAlgorithm *da,
 #ifdef MHD_SUPPORT_SHA512_256
 #ifdef mhd_SHA512_256_HAS_FINISH
     mhd_SHA512_256_finish (&da->ctx.sha512_256_ctx, digest);
-#ifdef _DEBUG
+#ifndef NDEBUG
     da->ready_for_hashing = false;
 #endif /* _DEBUG */
 #else  /* ! mhd_SHA512_256_HAS_FINISH */
     mhd_SHA512_256_finish_reset (&da->ctx.sha512_256_ctx, digest);
-#ifdef _DEBUG
+#ifndef NDEBUG
     da->ready_for_hashing = true;
 #endif /* _DEBUG */
 #endif /* ! mhd_SHA512_256_HAS_FINISH */
@@ -1804,7 +1804,7 @@ digest_calc_hash (struct DigestAlgorithm *da,
     mhd_UNREACHABLE ();
     break;
   }
-#ifdef _DEBUG
+#ifndef NDEBUG
   da->hashing = false;
 #endif /* _DEBUG */
 }
@@ -1831,7 +1831,7 @@ digest_reset (struct DigestAlgorithm *da)
     mhd_assert (da->ready_for_hashing);
 #  endif /* ! mhd_MD5_HAS_FINISH */
     mhd_MD5_reset (&(da->ctx.md5_ctx));
-#  ifdef _DEBUG
+#  ifndef NDEBUG
     da->ready_for_hashing = true;
 #  endif /* _DEBUG */
 #else  /* ! MHD_SUPPORT_MD5 */
@@ -1847,7 +1847,7 @@ digest_reset (struct DigestAlgorithm *da)
     mhd_assert (da->ready_for_hashing);
 #endif /* ! mhd_SHA256_HAS_FINISH */
     mhd_SHA256_reset (&(da->ctx.sha256_ctx));
-#ifdef _DEBUG
+#ifndef NDEBUG
     da->ready_for_hashing = true;
 #endif /* _DEBUG */
 #else  /* ! MHD_SUPPORT_SHA256 */
@@ -1863,7 +1863,7 @@ digest_reset (struct DigestAlgorithm *da)
     mhd_assert (da->ready_for_hashing);
 #  endif /* ! mhd_SHA512_256_HAS_FINISH */
     mhd_SHA512_256_reset (&(da->ctx.sha512_256_ctx));
-#  ifdef _DEBUG
+#  ifndef NDEBUG
     da->ready_for_hashing = true;
 #  endif /* _DEBUG */
 #else  /* ! MHD_SUPPORT_SHA512_256 */
@@ -1873,7 +1873,7 @@ digest_reset (struct DigestAlgorithm *da)
 
   case MHD_DIGEST_BASE_ALGO_INVALID:
   default:
-#ifdef _DEBUG
+#ifndef NDEBUG
     da->ready_for_hashing = false;
 #endif
     mhd_UNREACHABLE ();
diff --git a/src/mhd2/conn_get_info.c b/src/mhd2/conn_get_info.c
index b1887f8..a1eb3f1 100644
--- a/src/mhd2/conn_get_info.c
+++ b/src/mhd2/conn_get_info.c
@@ -26,6 +26,7 @@
 
 #include "mhd_sys_options.h"
 
+#include "mhd_assert.h"
 #include "mhd_unreachable.h"
 
 #include "mhd_connection.h"
diff --git a/src/mhd2/daemon_add_conn.c b/src/mhd2/daemon_add_conn.c
index 556640a..f774a6c 100644
--- a/src/mhd2/daemon_add_conn.c
+++ b/src/mhd2/daemon_add_conn.c
@@ -35,8 +35,7 @@
 
 #include "mhd_sys_options.h"
 
-#include "daemon_add_conn.h"
-
+#include "mhd_assert.h"
 #include "sys_bool_type.h"
 #include "sys_base_types.h"
 #include "sys_sockets_types.h"
@@ -64,7 +63,7 @@
 
 #include "daemon_logger.h"
 #include "mhd_mono_clock.h"
-#include "mhd_mempool.h"
+#include "mempool_funcs.h"
 #include "events_process.h"
 
 #include "response_from.h"
@@ -77,6 +76,8 @@
 
 #include "mhd_public_api.h"
 
+#include "daemon_add_conn.h"
+
 
 /**
  * Set initial internal states for the connection to start reading and
@@ -342,7 +343,8 @@ new_connection_process_inner (struct MHD_Daemon *restrict 
daemon,
    * intensively used memory area is allocated in "good"
    * (for the thread) memory region. It is important with
    * NUMA and/or complex cache hierarchy. */
-  connection->pool = mdh_pool_create (daemon->conns.cfg.mem_pool_size);
+  connection->pool = mhd_pool_create (daemon->conns.cfg.mem_pool_size,
+                                      daemon->conns.cfg.mem_pool_zeroing);
   if (NULL == connection->pool)
   { /* 'pool' creation failed */
     mhd_LOG_MSG (daemon, MHD_SC_POOL_MEM_ALLOC_FAILURE, \
@@ -859,7 +861,7 @@ mhd_daemon_accept_connection (struct MHD_Daemon *restrict 
daemon)
   bool sk_spipe_supprs;
   bool sk_cloexec;
   enum mhd_Tristate sk_non_ip;
-#if defined(_DEBUG) && defined (mhd_USE_ACCEPT4)
+#if !defined(NDEBUG) && defined (mhd_USE_ACCEPT4)
   const bool use_accept4 = ! daemon->dbg.avoid_accept4;
 #elif defined (mhd_USE_ACCEPT4)
   static const bool use_accept4 = true;
@@ -910,7 +912,7 @@ mhd_daemon_accept_connection (struct MHD_Daemon *restrict 
daemon)
     }
   }
 #endif /* mhd_USE_ACCEPT4 */
-#if ! defined(mhd_USE_ACCEPT4) || defined(_DEBUG)
+#if ! defined(mhd_USE_ACCEPT4) || !defined(NDEBUG)
   if (! use_accept4)
   {
     s = accept (fd,
diff --git a/src/mhd2/daemon_get_info.c b/src/mhd2/daemon_get_info.c
index b9e682e..bfd79ab 100644
--- a/src/mhd2/daemon_get_info.c
+++ b/src/mhd2/daemon_get_info.c
@@ -26,6 +26,7 @@
 
 #include "mhd_sys_options.h"
 
+#include "mhd_assert.h"
 #include "mhd_unreachable.h"
 
 #include "sys_base_types.h"
diff --git a/src/mhd2/daemon_options.h b/src/mhd2/daemon_options.h
index 9d6526a..ad365d3 100644
--- a/src/mhd2/daemon_options.h
+++ b/src/mhd2/daemon_options.h
@@ -157,6 +157,13 @@ struct DaemonOptions
   struct MHD_DaemonOptionValueAcceptPol accept_policy;
 
 
+  /**
+   * Value for #MHD_D_O_CONN_BUFF_ZEROING.
+   * buffer zeroing mode
+   */
+  enum MHD_ConnBufferZeroingMode conn_buff_zeroing;
+
+
   /**
    * Value for #MHD_D_O_PROTOCOL_STRICT_LEVEL.
    * the level of strictness
diff --git a/src/mhd2/daemon_set_options.c b/src/mhd2/daemon_set_options.c
index 5a885bf..27eca41 100644
--- a/src/mhd2/daemon_set_options.c
+++ b/src/mhd2/daemon_set_options.c
@@ -163,6 +163,9 @@ MHD_daemon_set_options (
       settings->accept_policy.v_apc = option->val.accept_policy.v_apc;
       settings->accept_policy.v_apc_cls = option->val.accept_policy.v_apc_cls;
       continue;
+    case MHD_D_O_CONN_BUFF_ZEROING:
+      settings->conn_buff_zeroing = option->val.conn_buff_zeroing;
+      continue;
     case MHD_D_O_PROTOCOL_STRICT_LEVEL:
       settings->protocol_strict_level.v_sl = 
option->val.protocol_strict_level.v_sl;
       settings->protocol_strict_level.v_how = 
option->val.protocol_strict_level.v_how;
diff --git a/src/mhd2/daemon_start.c b/src/mhd2/daemon_start.c
index cf64c99..180ce0e 100644
--- a/src/mhd2/daemon_start.c
+++ b/src/mhd2/daemon_start.c
@@ -26,6 +26,9 @@
 
 #include "mhd_sys_options.h"
 
+#include "mhd_assert.h"
+#include "mhd_unreachable.h"
+
 #include "sys_bool_type.h"
 #include "sys_base_types.h"
 #include "sys_malloc.h"
@@ -72,9 +75,6 @@
 #include "mhd_daemon.h"
 #include "daemon_options.h"
 
-#include "mhd_assert.h"
-#include "mhd_unreachable.h"
-
 #include "mhd_sockets_funcs.h"
 
 #include "mhd_lib_init.h"
@@ -332,14 +332,20 @@ enum mhd_CreateSktType
  * @param v6_tried true if IPv6 has been tried already
  * @param force_v6_any_dual true if IPv6 is forced with dual stack either
  *                          enabled or not
+ * @param prev_bnd_lstn_err if this function was already tried with another and
+ *                          failed to bind or to start listening then
+ *                          this parameter must be set to respecting status
+ *                          code, otherwise this parameter must be #MHD_SC_OK
  * @return #MHD_SC_OK on success,
- *         the error code otherwise
+ *         the error code otherwise (no error printed to log if result is
+ *         #MHD_SC_LISTEN_SOCKET_BIND_FAILED or #MHD_SC_LISTEN_FAILURE)
  */
 static enum MHD_StatusCode
-create_bind_listen_stream_socket (struct MHD_Daemon *restrict d,
-                                  struct DaemonOptions *restrict s,
-                                  bool v6_tried,
-                                  bool force_v6_any_dual)
+create_bind_listen_stream_socket_inner (struct MHD_Daemon *restrict d,
+                                       struct DaemonOptions *restrict s,
+                                       bool v6_tried,
+                                       bool force_v6_any_dual,
+                                       enum MHD_StatusCode prev_bnd_lstn_err)
 {
   MHD_Socket sk;
   enum mhd_CreateSktType sk_type;
@@ -695,17 +701,30 @@ create_bind_listen_stream_socket (struct MHD_Daemon 
*restrict d,
     {
 #ifdef HAVE_INET6
       if (mhd_SKT_IP_V4_WITH_FALLBACK == sk_type)
-        return create_bind_listen_stream_socket (d, s, v6_tried, true);
+        return create_bind_listen_stream_socket_inner (d,
+                                                      s,
+                                                      v6_tried,
+                                                      true,
+                                                      prev_bnd_lstn_err);
       if (mhd_SKT_IP_V4_WITH_V6_OPT == sk_type)
-        return create_bind_listen_stream_socket (d, s, true, false);
+        return create_bind_listen_stream_socket_inner (d,
+                                                      s,
+                                                      true,
+                                                      false,
+                                                      prev_bnd_lstn_err);
 #endif /* HAVE_INET6 */
 
+      if (MHD_SC_OK != prev_bnd_lstn_err)
+        return prev_bnd_lstn_err;
+
       if (mhd_SCKT_LERR_IS_AF ())
+      {
         mhd_LOG_MSG (d, MHD_SC_AF_NOT_AVAILABLE, \
                      "The requested socket address family is rejected " \
                      "by the OS");
-      else
-        mhd_LOG_MSG (d, MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET, \
+        return MHD_SC_AF_NOT_AVAILABLE;
+      }
+      mhd_LOG_MSG (d, MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET, \
                      "Failed to open listen socket");
 
       return MHD_SC_FAILED_TO_OPEN_LISTEN_SOCKET;
@@ -791,7 +810,11 @@ create_bind_listen_stream_socket (struct MHD_Daemon 
*restrict d,
             if (mhd_SKT_IP_V4_WITH_V6_OPT == sk_type)
             {
               (void) mhd_socket_close (sk);
-              return create_bind_listen_stream_socket (d, s, true, false);
+              return create_bind_listen_stream_socket_inner (d,
+                                                            s,
+                                                            true,
+                                                            false,
+                                                            prev_bnd_lstn_err);
             }
             if (! state_unknown)
             {
@@ -802,7 +825,9 @@ create_bind_listen_stream_socket (struct MHD_Daemon 
*restrict d,
                   d, MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_REJECTED, \
                   "Failed to disable IP dual-stack configuration " \
                   "for the listen socket");
-                ret = MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_REJECTED;
+                ret = (MHD_SC_OK == prev_bnd_lstn_err) ?
+                    MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_REJECTED :
+                    prev_bnd_lstn_err;
                 break;
               }
               else if (mhd_SKT_UNKNOWN != sk_type)
@@ -813,7 +838,9 @@ create_bind_listen_stream_socket (struct MHD_Daemon 
*restrict d,
                   "for the listen socket");
                 if (mhd_SKT_IP_DUAL_REQUIRED == sk_type)
                 {
-                  ret = MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_REJECTED;
+                  ret = (MHD_SC_OK == prev_bnd_lstn_err) ?
+                      MHD_SC_LISTEN_DUAL_STACK_CONFIGURATION_REJECTED :
+                      prev_bnd_lstn_err;
                   break;
                 }
               }
@@ -950,21 +977,28 @@ create_bind_listen_stream_socket (struct MHD_Daemon 
*restrict d,
       mhd_assert (0 != use_sa_size);
       if (0 != bind (sk, p_use_sa, use_sa_size))
       {
+        ret = (MHD_SC_OK == prev_bnd_lstn_err) ?
+            MHD_SC_LISTEN_SOCKET_BIND_FAILED : prev_bnd_lstn_err;
 #ifdef HAVE_INET6
         if (mhd_SKT_IP_V4_WITH_FALLBACK == sk_type)
         {
           (void) mhd_socket_close (sk);
-          return create_bind_listen_stream_socket (d, s, v6_tried, true);
+          return create_bind_listen_stream_socket_inner (d,
+                                                        s,
+                                                        v6_tried,
+                                                        true,
+                                                        ret);
         }
         if (mhd_SKT_IP_V4_WITH_V6_OPT == sk_type)
         {
           (void) mhd_socket_close (sk);
-          return create_bind_listen_stream_socket (d, s, true, false);
+          return create_bind_listen_stream_socket_inner (d,
+                                                        s,
+                                                        true,
+                                                        false,
+                                                        ret);
         }
 #endif /* HAVE_INET6 */
-        mhd_LOG_MSG (d, MHD_SC_LISTEN_SOCKET_BIND_FAILED, \
-                     "Failed to bind the listen socket");
-        ret = MHD_SC_LISTEN_SOCKET_BIND_FAILED;
         break;
       }
 
@@ -984,21 +1018,27 @@ create_bind_listen_stream_socket (struct MHD_Daemon 
*restrict d,
         }
         if (0 != listen (sk, accept_queue_len))
         {
+          ret = MHD_SC_LISTEN_FAILURE;
 #ifdef HAVE_INET6
           if (mhd_SKT_IP_V4_WITH_FALLBACK == sk_type)
           {
             (void) mhd_socket_close (sk);
-            return create_bind_listen_stream_socket (d, s, v6_tried, true);
+            return create_bind_listen_stream_socket_inner (d,
+                                                          s,
+                                                          v6_tried,
+                                                          true,
+                                                          ret);
           }
           if (mhd_SKT_IP_V4_WITH_V6_OPT == sk_type)
           {
             (void) mhd_socket_close (sk);
-            return create_bind_listen_stream_socket (d, s, true, false);
+            return create_bind_listen_stream_socket_inner (d,
+                                                          s,
+                                                          true,
+                                                          false,
+                                                          ret);
           }
 #endif /* HAVE_INET6 */
-          mhd_LOG_MSG (d, MHD_SC_LISTEN_FAILURE, \
-                       "Failed to start listening on the listen socket");
-          ret = MHD_SC_LISTEN_FAILURE;
           break;
         }
       }
@@ -1056,6 +1096,41 @@ create_bind_listen_stream_socket (struct MHD_Daemon 
*restrict d,
 }
 
 
+/**
+ * Create socket, bind to the address and start listening on the socket.
+ *
+ * The socket is assigned to the daemon as listening FD.
+ *
+ * @param d the daemon to use
+ * @param s the user settings
+ * @return #MHD_SC_OK on success,
+ *         the error code otherwise (no error printed to log if result is
+ *         #MHD_SC_LISTEN_SOCKET_BIND_FAILED or #MHD_SC_LISTEN_FAILURE)
+ */
+static enum MHD_StatusCode
+create_bind_listen_stream_socket (struct MHD_Daemon *restrict d,
+                                  struct DaemonOptions *restrict s)
+{
+  enum MHD_StatusCode ret;
+
+  ret = create_bind_listen_stream_socket_inner (d,
+                                               s,
+                                               false,
+                                               false,
+                                               MHD_SC_OK);
+#ifdef MHD_SUPPORT_LOG_FUNCTIONALITY
+  if (MHD_SC_LISTEN_SOCKET_BIND_FAILED == ret)
+    mhd_LOG_MSG (d, MHD_SC_LISTEN_SOCKET_BIND_FAILED, \
+                 "Failed to bind the listen socket");
+  else if (MHD_SC_LISTEN_FAILURE == ret)
+    mhd_LOG_MSG (d, MHD_SC_LISTEN_FAILURE, \
+                 "Failed to start listening on the listen socket");
+#endif /* MHD_SUPPORT_LOG_FUNCTIONALITY */
+
+  return ret;
+}
+
+
 #ifdef MHD_USE_GETSOCKNAME
 /**
  * Detect and set the type and port of the listening socket
@@ -1471,7 +1546,7 @@ daemon_init_net (struct MHD_Daemon *restrict d,
 
   if (MHD_SC_OK == ret)
   {
-    ret = create_bind_listen_stream_socket (d, s, false, false);
+    ret = create_bind_listen_stream_socket (d, s);
 
     if (MHD_SC_OK == ret)
     {
@@ -2351,6 +2426,20 @@ init_individual_conns (struct MHD_Daemon *restrict d,
   else if (256 > d->conns.cfg.mem_pool_size)
     d->conns.cfg.mem_pool_size = 256;
 
+  switch (s->conn_buff_zeroing)
+  {
+  case MHD_CONN_BUFFER_ZEROING_DISABLED:
+    d->conns.cfg.mem_pool_zeroing = MHD_MEMPOOL_ZEROING_NEVER;
+    break;
+  case MHD_CONN_BUFFER_ZEROING_BASIC:
+    d->conns.cfg.mem_pool_zeroing = MHD_MEMPOOL_ZEROING_ON_RESET;
+    break;
+  case MHD_CONN_BUFFER_ZEROING_HEAVY:
+  default:
+    d->conns.cfg.mem_pool_zeroing = MHD_MEMPOOL_ZEROING_ALWAYS;
+    break;
+  }
+
 #ifdef MHD_SUPPORT_UPGRADE
   mhd_DLINKEDL_INIT_LIST (&(d->conns.upgr),upgr_cleanup);
   if (! mhd_mutex_init (&(d->conns.upgr.ucu_lock)))
diff --git a/src/mhd2/dcc_action.c b/src/mhd2/dcc_action.c
index 6c786ed..34a3115 100644
--- a/src/mhd2/dcc_action.c
+++ b/src/mhd2/dcc_action.c
@@ -26,6 +26,8 @@
 
 #include "mhd_sys_options.h"
 
+#include "mhd_assert.h"
+
 #include <string.h>
 
 #include "mhd_dcc_action.h"
diff --git a/src/mhd2/events_process.c b/src/mhd2/events_process.c
index 6008c0e..1f67a00 100644
--- a/src/mhd2/events_process.c
+++ b/src/mhd2/events_process.c
@@ -1578,6 +1578,7 @@ update_statuses_from_eevents (struct MHD_Daemon *restrict 
d,
 static MHD_FN_PAR_NONNULL_ (1) bool
 get_all_net_updates_by_epoll (struct MHD_Daemon *restrict d)
 {
+  int max_events;
   int num_events;
   unsigned int events_processed;
   int max_wait;
@@ -1591,6 +1592,21 @@ get_all_net_updates_by_epoll (struct MHD_Daemon 
*restrict d)
 
   // TODO: add listen socket enable/disable
 
+  /* Minimise amount of data passed from userspace to kernel and back */
+  max_events = d->conns.cfg.count_limit;
+#ifdef MHD_SUPPORT_THREADS
+  ++max_events;
+#endif /* MHD_SUPPORT_THREADS */
+  if (MHD_INVALID_SOCKET != d->net.listen.fd)
+    ++max_events;
+  /* Make sure that one extra slot used to clearly detect that all events
+   * were gotten. */
+  ++max_events;
+  if (0 > max_events)
+    max_events = (int) (((unsigned int)~((unsigned int) 0)) >> 1);
+  if (max_events > (int) d->events.data.epoll.num_elements)
+    max_events = (int) d->events.data.epoll.num_elements;
+
   events_processed = 0;
   max_wait = get_max_wait (d); // TODO: use correct timeout value
   do
@@ -1604,13 +1620,13 @@ get_all_net_updates_by_epoll (struct MHD_Daemon 
*restrict d)
 #endif /* mhd_DEBUG_POLLING_FDS */
     num_events = epoll_wait (d->events.data.epoll.e_fd,
                              d->events.data.epoll.events,
-                             (int) d->events.data.epoll.num_elements,
+                             max_events,
                              max_wait);
 #ifdef mhd_DEBUG_POLLING_FDS
     fprintf (stderr,
              "### (Finished) epoll_wait(%d, events, %d, %d) -> %d\n",
              d->events.data.epoll.e_fd,
-             (int) d->events.data.epoll.num_elements,
+             max_events,
              max_wait,
              num_events);
 #endif /* mhd_DEBUG_POLLING_FDS */
@@ -1628,11 +1644,16 @@ get_all_net_updates_by_epoll (struct MHD_Daemon 
*restrict d)
     }
     if (! update_statuses_from_eevents (d, (unsigned int) num_events))
       return false;
+    if (max_events > num_events)
+      return true; /* All events have been read */
+
+    /* Use all buffer for the next getting events round(s) */
+    max_events = d->events.data.epoll.num_elements;
+    max_wait = 0; /* Do not block on the next getting events rounds */
 
     events_processed += (unsigned int) num_events; /* Avoid reading too many 
events */
-  } while ((((unsigned int) num_events) == d->events.data.epoll.num_elements) 
&&
-           ((events_processed < d->conns.cfg.count_limit)
-            || (events_processed < d->conns.cfg.count_limit + 2)));
+  } while ((events_processed < d->conns.cfg.count_limit)
+            || (events_processed < d->conns.cfg.count_limit + 2));
 
   return true;
 }
diff --git a/src/mhd2/mhd_mempool.c b/src/mhd2/mempool_funcs.c
similarity index 77%
rename from src/mhd2/mhd_mempool.c
rename to src/mhd2/mempool_funcs.c
index d208067..c881f16 100644
--- a/src/mhd2/mhd_mempool.c
+++ b/src/mhd2/mempool_funcs.c
@@ -19,7 +19,7 @@
 */
 
 /**
- * @file src/mhd2/mhd_mempool.h
+ * @file src/mhd2/mempool_funcs.c
  * @brief memory pool
  * @author Christian Grothoff
  * @author Karlson2k (Evgeny Grin)
@@ -28,8 +28,9 @@
  * + Detect mmap() in configure (it is purely optional!)
  */
 #include "mhd_sys_options.h"
+#include "mempool_funcs.h"
+#include "compat_calloc.h"
 
-#include "mhd_mempool.h"
 #ifdef HAVE_STDLIB_H
 #  include <stdlib.h>
 #endif /* HAVE_STDLIB_H */
@@ -84,26 +85,34 @@
 #include <sanitizer/asan_interface.h>
 #endif /* MHD_ASAN_POISON_ACTIVE */
 
-/* define MAP_ANONYMOUS for Mac OS X */
-#if defined(MAP_ANON) && ! defined(MAP_ANONYMOUS)
-#define MAP_ANONYMOUS MAP_ANON
+#if defined(MAP_ANONYMOUS)
+#  define mhd_MAP_ANONYMOUS MAP_ANONYMOUS
 #endif
-#if defined(_WIN32)
-#define MAP_FAILED NULL
-#elif ! defined(MAP_FAILED)
-#define MAP_FAILED ((void*) -1)
+
+#if ! defined(mhd_MAP_ANONYMOUS) && defined(MAP_ANON)
+#  define mhd_MAP_ANONYMOUS MAP_ANON
 #endif
 
-/**
- * Align to 2x word size (as GNU libc does).
- */
-#define ALIGN_SIZE (2 * sizeof(void*))
+#if defined(mhd_MAP_ANONYMOUS) || defined(_WIN32)
+#  define mhd_USE_LARGE_ALLOCS 1
+#endif
+
+#ifdef mhd_USE_LARGE_ALLOCS
+#  if defined(_WIN32)
+#    define mhd_MAP_FAILED NULL
+#  elif defined(MAP_FAILED)
+#    define mhd_MAP_FAILED MAP_FAILED
+#  else
+#    define mhd_MAP_FAILED ((void*) -1)
+#  endif
+#endif
 
 /**
  * Round up 'n' to a multiple of ALIGN_SIZE.
  */
-#define mhd_ROUND_TO_ALIGN(n) (((n) + (ALIGN_SIZE - 1)) \
-                               / (ALIGN_SIZE) *(ALIGN_SIZE))
+#define mhd_ROUND_TO_ALIGN(n) \
+  (((n) + (mhd_MEMPOOL_ALIGN_SIZE - 1)) \
+   / (mhd_MEMPOOL_ALIGN_SIZE) *(mhd_MEMPOOL_ALIGN_SIZE))
 
 
 #ifndef MHD_ASAN_POISON_ACTIVE
@@ -124,7 +133,7 @@
 #  define mp_ptr_diff_(p1,p2) \
         ((size_t) (((const uint8_t*) (p1)) - ((const uint8_t*) (p2))))
 #else  /* MHD_ASAN_POISON_ACTIVE */
-#  define mhd_RED_ZONE_SIZE (ALIGN_SIZE)
+#  define mhd_RED_ZONE_SIZE (mhd_MEMPOOL_ALIGN_SIZE)
 #  define mhd_ROUND_TO_ALIGN_PLUS_RED_ZONE(n) \
         (mhd_ROUND_TO_ALIGN (n) + mhd_RED_ZONE_SIZE)
 #  define mhd_POISON_MEMORY(pointer, size) \
@@ -147,7 +156,7 @@
                    ((uintptr_t) ((const uint8_t*) (p2)))))
 #elif defined(FUNC_ATTR_PTRCOMPARE_WORKS) && \
   defined(FUNC_ATTR_PTRSUBTRACT_WORKS)
-#    ifdef _DEBUG
+#    ifndef NDEBUG
 /**
  * Boolean 'true' if the first pointer is less or equal the second pointer
  */
@@ -173,7 +182,7 @@ mp_ptr_diff_ (const void *p1, const void *p2)
 
 
 #  elif defined(FUNC_ATTR_NOSANITIZE_WORKS)
-#    ifdef _DEBUG
+#    ifndef NDEBUG
 /**
  * Boolean 'true' if the first pointer is less or equal the second pointer
  */
@@ -202,24 +211,24 @@ mp_ptr_diff_ (const void *p1, const void *p2)
 #  endif /* ! FUNC_ATTR_NOSANITIZE_WORKS */
 #endif /* MHD_ASAN_POISON_ACTIVE */
 
+#ifdef mhd_USE_LARGE_ALLOCS
 /**
  * Size of memory page
  */
 static size_t MHD_sys_page_size_ = (size_t)
-#if defined(MHD_USE_PAGESIZE_MACRO_STATIC)
+#  if defined(MHD_USE_PAGESIZE_MACRO_STATIC)
                                    PAGESIZE;
-#elif defined(MHD_USE_PAGE_SIZE_MACRO_STATIC)
+#  elif defined(MHD_USE_PAGE_SIZE_MACRO_STATIC)
                                    PAGE_SIZE;
-#else  /* ! MHD_USE_PAGE_SIZE_MACRO_STATIC */
+#  else  /* ! MHD_USE_PAGE_SIZE_MACRO_STATIC */
                                    mhd_FALLBACK_PAGE_SIZE; /* Default fallback 
value */
-#endif /* ! MHD_USE_PAGE_SIZE_MACRO_STATIC */
+#  endif /* ! MHD_USE_PAGE_SIZE_MACRO_STATIC */
+#endif /* mhd_USE_LARGE_ALLOCS */
 
-/**
- * Initialise values for memory pools
- */
 void
 mhd_init_mem_pools (void)
 {
+#ifdef mhd_USE_LARGE_ALLOCS
 #ifdef MHD_SC_PAGESIZE
   long result;
   result = sysconf (MHD_SC_PAGESIZE);
@@ -234,7 +243,9 @@ mhd_init_mem_pools (void)
 #else
   MHD_sys_page_size_ = (size_t) mhd_DEF_PAGE_SIZE;
 #endif /* _WIN32 */
-  mhd_assert (0 == (MHD_sys_page_size_ % ALIGN_SIZE));
+  mhd_assert (0 == (MHD_sys_page_size_ % mhd_MEMPOOL_ALIGN_SIZE));
+#endif /* mhd_USE_LARGE_ALLOCS */
+  (void) 0;
 }
 
 
@@ -265,23 +276,24 @@ struct mhd_MemoryPool
    */
   size_t end;
 
+#ifdef mhd_USE_LARGE_ALLOCS
   /**
    * 'false' if pool was malloc'ed, 'true' if mmapped (VirtualAlloc'ed for 
W32).
    */
-  bool is_mmap;
+  bool is_large_alloc;
+#endif
 
-  // TODO: implement *optional* zeroing on reset on reallocs
+  /**
+   * Memory allocation zeroing mode
+   */
+  enum mhd_MemPoolZeroing zeroing;
 };
 
 
-/**
- * Create a memory pool.
- *
- * @param max maximum size of the pool
- * @return NULL on error
- */
-MHD_INTERNAL struct mhd_MemoryPool *
-mdh_pool_create (size_t max)
+MHD_INTERNAL mhd_FN_RET_UNALIASED mhd_FN_OBJ_CONSTRUCTOR(mhd_pool_destroy)
+struct mhd_MemoryPool *
+mhd_pool_create (size_t max,
+                 enum mhd_MemPoolZeroing zeroing)
 {
   struct mhd_MemoryPool *pool;
   size_t alloc_size;
@@ -291,52 +303,53 @@ mdh_pool_create (size_t max)
   pool = (struct mhd_MemoryPool *) malloc (sizeof (struct mhd_MemoryPool));
   if (NULL == pool)
     return NULL;
-#if defined(MAP_ANONYMOUS) || defined(_WIN32)
+  pool->zeroing = zeroing;
+#ifdef mhd_USE_LARGE_ALLOCS
+  pool->is_large_alloc = false;
   if ( (max <= 32 * 1024) ||
        (max < MHD_sys_page_size_ * 4 / 3) )
   {
-    pool->memory = (uint8_t *) MAP_FAILED;
+    pool->memory = (uint8_t *) mhd_MAP_FAILED;
   }
   else
   {
     /* Round up allocation to page granularity. */
     alloc_size = max + MHD_sys_page_size_ - 1;
     alloc_size -= alloc_size % MHD_sys_page_size_;
-#if defined(MAP_ANONYMOUS) && ! defined(_WIN32)
+    pool->is_large_alloc = true;
+#  if defined(mhd_MAP_ANONYMOUS)
     pool->memory = (uint8_t *) mmap (NULL,
                                      alloc_size,
                                      PROT_READ | PROT_WRITE,
                                      MAP_PRIVATE | MAP_ANONYMOUS,
                                      -1,
                                      0);
-#elif defined(_WIN32)
+#  else  /* ! mhd_MAP_ANONYMOUS */
     pool->memory = (uint8_t *) VirtualAlloc (NULL,
                                              alloc_size,
                                              MEM_COMMIT | MEM_RESERVE,
                                              PAGE_READWRITE);
-#endif /* _WIN32 */
+#  endif /* ! mhd_MAP_ANONYMOUS */
   }
-#else  /* ! _WIN32 && ! MAP_ANONYMOUS */
-  pool->memory = (uint8_t *) MAP_FAILED;
-#endif /* ! _WIN32 && ! MAP_ANONYMOUS */
-  if (MAP_FAILED == pool->memory)
+#else  /* !mhd_USE_LARGE_ALLOCS */
+  if (mhd_MAP_FAILED != pool->memory)
+    pool->is_large_alloc = true;
+  else
+#endif /* !mhd_USE_LARGE_ALLOCS*/
+  if (! 0)
   {
     alloc_size = mhd_ROUND_TO_ALIGN (max);
-    pool->memory = (uint8_t *) malloc (alloc_size);
+    if (MHD_MEMPOOL_ZEROING_NEVER == zeroing)
+      pool->memory = (uint8_t *) malloc (alloc_size);
+    else
+      pool->memory = (uint8_t *) mhd_calloc (1, alloc_size);
     if (((uint8_t *) NULL) == pool->memory)
     {
       free (pool);
       return NULL;
     }
-    pool->is_mmap = false;
-  }
-#if defined(MAP_ANONYMOUS) || defined(_WIN32)
-  else
-  {
-    pool->is_mmap = true;
   }
-#endif /* _WIN32 || MAP_ANONYMOUS */
-  mhd_assert (0 == (((uintptr_t) pool->memory) % ALIGN_SIZE));
+  mhd_assert (0 == (((uintptr_t) pool->memory) % mhd_MEMPOOL_ALIGN_SIZE));
   pool->pos = 0;
   pool->end = alloc_size;
   pool->size = alloc_size;
@@ -346,11 +359,6 @@ mdh_pool_create (size_t max)
 }
 
 
-/**
- * Destroy a memory pool.
- *
- * @param pool memory pool to destroy
- */
 MHD_INTERNAL void
 mhd_pool_destroy (struct mhd_MemoryPool *restrict pool)
 {
@@ -361,29 +369,27 @@ mhd_pool_destroy (struct mhd_MemoryPool *restrict pool)
   mhd_assert (pool->size >= pool->end - pool->pos);
   mhd_assert (pool->pos == mhd_ROUND_TO_ALIGN (pool->pos));
   mhd_UNPOISON_MEMORY (pool->memory, pool->size);
-  if (! pool->is_mmap)
-    free (pool->memory);
-  else
-#if defined(MAP_ANONYMOUS) && ! defined(_WIN32)
+#ifdef mhd_USE_LARGE_ALLOCS
+  if (pool->is_large_alloc)
+  {
+#  if defined(mhd_MAP_ANONYMOUS)
     munmap (pool->memory,
             pool->size);
-#elif defined(_WIN32)
+#  else
     VirtualFree (pool->memory,
                  0,
                  MEM_RELEASE);
-#else
-    abort ();
-#endif
+#  endif
+  }
+  else
+#endif /* mhd_USE_LARGE_ALLOCS*/
+  if (! 0)
+    free (pool->memory);
+
   free (pool);
 }
 
 
-/**
- * Check how much memory is left in the @a pool
- *
- * @param pool pool to check
- * @return number of bytes still available in @a pool
- */
 MHD_INTERNAL size_t
 mhd_pool_get_free (struct mhd_MemoryPool *restrict pool)
 {
@@ -398,18 +404,8 @@ mhd_pool_get_free (struct mhd_MemoryPool *restrict pool)
 }
 
 
-/**
- * Allocate size bytes from the pool.
- *
- * @param pool memory pool to use for the operation
- * @param size number of bytes to allocate
- * @param from_end allocate from end of pool (set to 'true');
- *        use this for small, persistent allocations that
- *        will never be reallocated
- * @return NULL if the pool cannot support size more
- *         bytes
- */
-MHD_INTERNAL void *
+MHD_INTERNAL mhd_FN_RET_UNALIASED mhd_FN_RET_SIZED(2)
+mhd_FN_RET_ALIGNED(mhd_MEMPOOL_ALIGN_SIZE) void *
 mhd_pool_allocate (struct mhd_MemoryPool *restrict pool,
                    size_t size,
                    bool from_end)
@@ -440,16 +436,6 @@ mhd_pool_allocate (struct mhd_MemoryPool *restrict pool,
 }
 
 
-/**
- * Checks whether allocated block is re-sizable in-place.
- * If block is not re-sizable in-place, it still could be shrunk, but freed
- * memory will not be re-used until reset of the pool.
- * @param pool the memory pool to use
- * @param block the pointer to the allocated block to check
- * @param block_size the size of the allocated @a block
- * @return true if block can be resized in-place in the optimal way,
- *         false otherwise
- */
 MHD_INTERNAL bool
 mhd_pool_is_resizable_inplace (struct mhd_MemoryPool *restrict pool,
                                void *restrict block,
@@ -472,26 +458,8 @@ mhd_pool_is_resizable_inplace (struct mhd_MemoryPool 
*restrict pool,
 }
 
 
-/**
- * Try to allocate @a size bytes memory area from the @a pool.
- *
- * If allocation fails, @a required_bytes is updated with size required to be
- * freed in the @a pool from rellocatable area to allocate requested number
- * of bytes.
- * Allocated memory area is always not rellocatable ("from end").
- *
- * @param pool memory pool to use for the operation
- * @param size the size of memory in bytes to allocate
- * @param[out] required_bytes the pointer to variable to be updated with
- *                            the size of the required additional free
- *                            memory area, set to 0 if function succeeds.
- *                            Cannot be NULL.
- * @return the pointer to allocated memory area if succeed,
- *         NULL if the pool doesn't have enough space, required_bytes is 
updated
- *         with amount of space needed to be freed in rellocatable area or
- *         set to SIZE_MAX if requested size is too large for the pool.
- */
-MHD_INTERNAL void *
+MHD_INTERNAL mhd_FN_RET_UNALIASED mhd_FN_RET_SIZED(2)
+mhd_FN_RET_ALIGNED(mhd_MEMPOOL_ALIGN_SIZE) void *
 mhd_pool_try_alloc (struct mhd_MemoryPool *restrict pool,
                     size_t size,
                     size_t *restrict required_bytes)
@@ -526,24 +494,8 @@ mhd_pool_try_alloc (struct mhd_MemoryPool *restrict pool,
 }
 
 
-/**
- * Reallocate a block of memory obtained from the pool.
- * This is particularly efficient when growing or
- * shrinking the block that was last (re)allocated.
- * If the given block is not the most recently
- * (re)allocated block, the memory of the previous
- * allocation may be not released until the pool is
- * destroyed or reset.
- *
- * @param pool memory pool to use for the operation
- * @param old the existing block
- * @param old_size the size of the existing block
- * @param new_size the new size of the block
- * @return new address of the block, or
- *         NULL if the pool cannot support @a new_size
- *         bytes (old continues to be valid for @a old_size)
- */
-MHD_INTERNAL void *
+MHD_INTERNAL mhd_FN_RET_SIZED(4) mhd_FN_RET_ALIGNED(mhd_MEMPOOL_ALIGN_SIZE)
+void *
 mhd_pool_reallocate (struct mhd_MemoryPool *restrict pool,
                      void *restrict old,
                      size_t old_size,
@@ -578,7 +530,8 @@ mhd_pool_reallocate (struct mhd_MemoryPool *restrict pool,
     /* Try resizing in-place */
     if (shrinking)
     {     /* Shrinking in-place, zero-out freed part */
-      memset ((uint8_t *) old + new_size, 0, old_size - new_size);
+      if (MHD_MEMPOOL_ZEROING_ON_RESET < pool->zeroing)
+        memset ((uint8_t *) old + new_size, 0, old_size - new_size);
       mhd_POISON_MEMORY ((uint8_t *) old + new_size, old_size - new_size);
     }
     if (pool->pos ==
@@ -616,25 +569,14 @@ mhd_pool_reallocate (struct mhd_MemoryPool *restrict pool,
     /* Move data to new block, old block remains allocated */
     memcpy (new_blc, old, old_size);
     /* Zero-out old block */
-    memset (old, 0, old_size);
+    if (MHD_MEMPOOL_ZEROING_ON_RESET < pool->zeroing)
+      memset (old, 0, old_size);
     mhd_POISON_MEMORY (old, old_size);
   }
   return new_blc;
 }
 
 
-/**
- * Deallocate a block of memory obtained from the pool.
- *
- * If the given block is not the most recently
- * (re)allocated block, the memory of the this block
- * allocation may be not released until the pool is
- * destroyed or reset.
- *
- * @param pool memory pool to use for the operation
- * @param block the allocated block, the NULL is tolerated
- * @param block_size the size of the allocated block
- */
 MHD_INTERNAL void
 mhd_pool_deallocate (struct mhd_MemoryPool *restrict pool,
                      void *restrict block,
@@ -655,7 +597,8 @@ mhd_pool_deallocate (struct mhd_MemoryPool *restrict pool,
     /* Zero-out deallocated region */
     if (0 != block_size)
     {
-      memset (block, 0, block_size);
+      if (MHD_MEMPOOL_ZEROING_ON_RESET < pool->zeroing)
+        memset (block, 0, block_size);
       mhd_POISON_MEMORY (block, block_size);
     }
 #if ! defined(MHD_FAVOR_SMALL_CODE) && ! defined(MHD_ASAN_POISON_ACTIVE)
@@ -726,20 +669,8 @@ mhd_pool_deallocate (struct mhd_MemoryPool *restrict pool,
 }
 
 
-/**
- * Clear all entries from the memory pool except
- * for @a keep of the given @a copy_bytes.  The pointer
- * returned should be a buffer of @a new_size where
- * the first @a copy_bytes are from @a keep.
- *
- * @param pool memory pool to use for the operation
- * @param keep pointer to the entry to keep (maybe NULL)
- * @param copy_bytes how many bytes need to be kept at this address
- * @param new_size how many bytes should the allocation we return have?
- *                 (should be larger or equal to @a copy_bytes)
- * @return addr new address of @a keep (if it had to change)
- */
-MHD_INTERNAL void *
+MHD_INTERNAL mhd_FN_RET_SIZED(4) mhd_FN_RET_ALIGNED(mhd_MEMPOOL_ALIGN_SIZE)
+void *
 mhd_pool_reset (struct mhd_MemoryPool *restrict pool,
                 void *restrict keep,
                 size_t copy_bytes,
@@ -766,15 +697,15 @@ mhd_pool_reset (struct mhd_MemoryPool *restrict pool,
                keep,
                copy_bytes);
   }
-  /* technically not needed, but safer to zero out */
-  if (pool->size > copy_bytes)
+  if ((MHD_MEMPOOL_ZEROING_NEVER != pool->zeroing) &&
+      (pool->size > copy_bytes))
   {
     size_t to_zero;   /** Size of area to zero-out */
 
     to_zero = pool->size - copy_bytes;
     mhd_UNPOISON_MEMORY (pool->memory + copy_bytes, to_zero);
-#ifdef _WIN32
-    if (pool->is_mmap)
+#if defined(mhd_USE_LARGE_ALLOCS) && defined(_WIN32)
+    if (pool->is_large_alloc)
     {
       size_t to_recommit;     /** Size of decommitted and re-committed area. */
       uint8_t *recommit_addr;
@@ -797,7 +728,7 @@ mhd_pool_reset (struct mhd_MemoryPool *restrict pool,
           abort ();      /* Serious error, must never happen */
       }
     }
-#endif /* _WIN32 */
+#endif /* mhd_USE_LARGE_ALLOCS && _WIN32 */
     memset (&pool->memory[copy_bytes],
             0,
             to_zero);
diff --git a/src/mhd2/mhd_mempool.h b/src/mhd2/mempool_funcs.h
similarity index 81%
rename from src/mhd2/mhd_mempool.h
rename to src/mhd2/mempool_funcs.h
index bc7dac4..5c4a393 100644
--- a/src/mhd2/mhd_mempool.h
+++ b/src/mhd2/mempool_funcs.h
@@ -1,7 +1,7 @@
 /*
      This file is part of libmicrohttpd
      Copyright (C) 2007--2024 Daniel Pittman and Christian Grothoff
-     Copyright (C) 2016--2024 Evgeny Grin (Karlson2k)
+     Copyright (C) 2016--2025 Evgeny Grin (Karlson2k)
 
      This library is free software; you can redistribute it and/or
      modify it under the terms of the GNU Lesser General Public
@@ -19,7 +19,7 @@
 */
 
 /**
- * @file src/mhd2/mhd_mempool.h
+ * @file src/mhd2/mempool_funcs.h
  * @brief memory pool; mostly used for efficient (de)allocation
  *        for each connection and bounding memory use for each
  *        request
@@ -27,44 +27,49 @@
  * @author Karlson2k (Evgeny Grin)
  */
 
-#ifndef MHD_MEMPOOL_H
-#define MHD_MEMPOOL_H 1
+#ifndef MHD_MEMPOOL_FUNCS_H
+#define MHD_MEMPOOL_FUNCS_H 1
 
 #include "mhd_sys_options.h"
 #include "sys_base_types.h"
 #include "sys_bool_type.h"
+#include "mempool_types.h"
 
 /**
- * Opaque handle for a memory pool.
- * Pools are not reentrant and must not be used
- * by multiple threads.
+ * Alignment size used by memory pool function.
+ * This is 2x pointer size (similar to GNU libc).
  */
-struct mhd_MemoryPool;
+#define mhd_MEMPOOL_ALIGN_SIZE (2 * sizeof(void*))
 
 /**
- * Initialize values for memory pools
+ * Perform one-time initialisation of the internal values required for
+ * memory pools functions
  */
 void
 mhd_init_mem_pools (void);
 
 
 /**
- * Create a memory pool.
+ * Destroy a memory pool.
  *
- * @param max maximum size of the pool
- * @return NULL on error
+ * @param pool memory pool to destroy
  */
-MHD_INTERNAL struct mhd_MemoryPool *
-mdh_pool_create (size_t max);
+MHD_INTERNAL void
+mhd_pool_destroy (struct mhd_MemoryPool *restrict pool);
 
 
 /**
- * Destroy a memory pool.
+ * Create a memory pool.
  *
- * @param pool memory pool to destroy
+ * @param max maximum size of the pool
+ * @param zeroing the request zeroing of allocated and deallocated memory
+ * @return pointer to the new object on success,
+ *         NULL on error
  */
-MHD_INTERNAL void
-mhd_pool_destroy (struct mhd_MemoryPool *restrict pool);
+MHD_INTERNAL struct mhd_MemoryPool *
+mhd_pool_create (size_t max,
+                 enum mhd_MemPoolZeroing zeroing)
+mhd_FN_RET_UNALIASED mhd_FN_OBJ_CONSTRUCTOR(mhd_pool_destroy);
 
 
 /**
@@ -74,14 +79,16 @@ mhd_pool_destroy (struct mhd_MemoryPool *restrict pool);
  * @param size number of bytes to allocate
  * @param from_end allocate from end of pool (set to 'true');
  *        use this for small, persistent allocations that
- *        will never be reallocated
- * @return NULL if the pool cannot support size more
- *         bytes
+ *        will not be reallocated until pool reset
+ * @return pointer to the new allocated memory region on success,
+ *         NULL if the pool does not have enough free memory.
  */
 MHD_INTERNAL void *
 mhd_pool_allocate (struct mhd_MemoryPool *restrict pool,
                    size_t size,
-                   bool from_end);
+                   bool from_end)
+mhd_FN_RET_UNALIASED mhd_FN_RET_SIZED(2)
+mhd_FN_RET_ALIGNED(mhd_MEMPOOL_ALIGN_SIZE);
 
 /**
  * Checks whether allocated block is re-sizable in-place.
@@ -120,7 +127,9 @@ mhd_pool_is_resizable_inplace (struct mhd_MemoryPool 
*restrict pool,
 MHD_INTERNAL void *
 mhd_pool_try_alloc (struct mhd_MemoryPool *restrict pool,
                     size_t size,
-                    size_t *restrict required_bytes);
+                    size_t *restrict required_bytes)
+mhd_FN_RET_UNALIASED mhd_FN_RET_SIZED(2)
+mhd_FN_RET_ALIGNED(mhd_MEMPOOL_ALIGN_SIZE);
 
 
 /**
@@ -144,7 +153,8 @@ MHD_INTERNAL void *
 mhd_pool_reallocate (struct mhd_MemoryPool *restrict pool,
                      void *restrict old,
                      size_t old_size,
-                     size_t new_size);
+                     size_t new_size)
+mhd_FN_RET_SIZED(4) mhd_FN_RET_ALIGNED(mhd_MEMPOOL_ALIGN_SIZE);
 
 
 /**
@@ -192,6 +202,7 @@ MHD_INTERNAL void *
 mhd_pool_reset (struct mhd_MemoryPool *restrict pool,
                 void *restrict keep,
                 size_t copy_bytes,
-                size_t new_size);
+                size_t new_size)
+mhd_FN_RET_SIZED(4) mhd_FN_RET_ALIGNED(mhd_MEMPOOL_ALIGN_SIZE);
 
-#endif /* ! MHD_MEMPOOL_H */
+#endif /* ! MHD_MEMPOOL_FUNCS_H */
diff --git a/src/mhd2/mempool_types.h b/src/mhd2/mempool_types.h
new file mode 100644
index 0000000..a2c8da5
--- /dev/null
+++ b/src/mhd2/mempool_types.h
@@ -0,0 +1,64 @@
+/*
+  This file is part of GNU libmicrohttpd
+  Copyright (C) 2025 Evgeny Grin (Karlson2k)
+
+  GNU libmicrohttpd is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  GNU libmicrohttpd is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, see
+  <https://www.gnu.org/licenses/>.
+
+*/
+
+/**
+ * @file src/mhd2/mempool_types.h
+ * @brief Special types for use with memory pool functions
+ * @author Karlson2k (Evgeny Grin)
+ */
+
+#ifndef MHD_MEMPOOL_TYPES_H
+#define MHD_MEMPOOL_TYPES_H 1
+
+#include "mhd_sys_options.h"
+
+/**
+ * Opaque handle for a memory pool.
+ * Pools are not reentrant and must not be used
+ * by multiple threads.
+ */
+struct mhd_MemoryPool;
+
+/**
+ * Controls zeroing of allocated and deallocated memory
+ */
+enum MHD_FIXED_ENUM_ mhd_MemPoolZeroing
+{
+  /**
+   * Never zero the memory.
+   * Allocated memory may contain garbage.
+   * Deallocated regions are not wiped.
+   */
+  MHD_MEMPOOL_ZEROING_NEVER = 0
+  ,
+  /**
+   * Zero memory on pool initialisation and on every reset operation.
+   * Deallocated and re-allocated memory areas are not wiped.
+   */
+  MHD_MEMPOOL_ZEROING_ON_RESET
+  ,
+  /**
+   * Zero memory on pool creation, on every reset and
+   * on every deallocation/re-allocation.
+   */
+  MHD_MEMPOOL_ZEROING_ALWAYS
+};
+
+#endif /* ! MHD_MEMPOOL_TYPES_H */
diff --git a/src/mhd2/mhd_atomic_counter.h b/src/mhd2/mhd_atomic_counter.h
index f0d4f35..2e1cde8 100644
--- a/src/mhd2/mhd_atomic_counter.h
+++ b/src/mhd2/mhd_atomic_counter.h
@@ -48,10 +48,18 @@
 
 #ifdef MHD_SUPPORT_THREADS
 
+#  if defined(MHD_SUPPORT_ATOMIC_COUNTERS) && !defined(__STDC_NO_ATOMICS__)
+
+/**
+ * Atomic operations are based native compiler support for atomics
+ */
+#    define mhd_ATOMIC_NATIVE 1
+#  else
 /**
  * Atomic operations are based on locks
  */
-#  define mhd_ATOMIC_BY_LOCKS 1
+#    define mhd_ATOMIC_BY_LOCKS 1
+#  endif
 
 #else  /* ! MHD_SUPPORT_THREADS */
 
@@ -61,8 +69,21 @@
 #  define mhd_ATOMIC_SINGLE_THREAD 1
 #endif /* ! MHD_SUPPORT_THREADS */
 
+#if defined(mhd_ATOMIC_NATIVE)
+#  include <stdatomic.h>
 
-#if defined(mhd_ATOMIC_BY_LOCKS)
+/**
+ * The atomic counter
+ */
+struct mhd_AtomicCounter
+{
+  /**
+   * Counter value.
+   */
+  volatile _Atomic mhd_ATOMIC_COUNTER_TYPE count;
+};
+
+#elif defined(mhd_ATOMIC_BY_LOCKS)
 #  include "mhd_locks.h"
 #  include "sys_bool_type.h"
 
@@ -98,7 +119,7 @@ struct mhd_AtomicCounter
 #endif /* mhd_ATOMIC_SINGLE_THREAD */
 
 
-#if defined(mhd_ATOMIC_BY_LOCKS)
+#if defined(mhd_ATOMIC_NATIVE)
 
 /**
  * Initialise the counter to specified value.
@@ -109,8 +130,68 @@ struct mhd_AtomicCounter
  *          already.
  */
 #  define mhd_atomic_counter_init(pcnt,initial_value) \
-        ((pcnt)->count = (initial_value), \
-         mhd_mutex_init_short (&((pcnt)->lock)))
+    (atomic_init (&((pcnt)->count), (initial_value)), (! 0))
+
+/**
+ * Deinitialise the counter.
+ * @param pcnt the pointer to the counter to deinitialise
+ * @warning Must be called only for the counters that has been initialised.
+ */
+#  define mhd_atomic_counter_deinit(pcnt) ((void) 0)
+
+/**
+ * Atomically increment the value of the counter
+ * @param pcnt the pointer to the counter to increment
+ */
+#  define mhd_atomic_counter_inc(pcnt)               \
+  do { atomic_fetch_add_explicit(&((pcnt)->count), 1, \
+                                 memory_order_relaxed); } while (0)
+
+/**
+ * Atomically increment the value of the counter and return the result
+ * @param pcnt the pointer to the counter to increment
+ * @return the final/resulting counter value
+ */
+#  define mhd_atomic_counter_inc_get(pcnt) \
+    (atomic_fetch_add_explicit(&((pcnt)->count), 1, memory_order_relaxed) + 1)
+
+/**
+ * Atomically decrement the value of the counter and return the result
+ * @param pcnt the pointer to the counter to decrement
+ * @return the final/resulting counter value
+ */
+#  define mhd_atomic_counter_dec_get(pcnt) \
+    (atomic_fetch_sub_explicit(&((pcnt)->count), 1, memory_order_release) - 1)
+
+/**
+ * Atomically get the value of the counter
+ * @param pcnt the pointer to the counter to get
+ * @return the counter value
+ */
+#  define mhd_atomic_counter_get(pcnt) \
+    (atomic_load_explicit(&((pcnt)->count), memory_order_relaxed))
+
+/**
+ * Atomically increment the value of the counter and return the result.
+ * The value is allowed to overflow and get back to zero.
+ * @param pcnt the pointer to the counter to increment
+ * @return the final/resulting counter value
+ */
+#  define mhd_atomic_counter_inc_wrap_get(pcnt) \
+    mhd_atomic_counter_inc_get (pcnt)
+#elif defined(mhd_ATOMIC_BY_LOCKS)
+
+/**
+ * Initialise the counter to specified value.
+ * @param pcnt the pointer to the counter to initialise
+ * @param initial_value the initial value for the counter
+ * @return 'true' if succeed, "false' if failed
+ * @warning Must not be called for the counters that has been initialised
+ *          already.
+ */
+#  define mhd_atomic_counter_init(pcnt,initial_value) \
+          ((pcnt)->count = (initial_value),           \
+           mhd_mutex_init_short (&((pcnt)->lock)))
 
 /**
  * Deinitialise the counter.
@@ -118,15 +199,15 @@ struct mhd_AtomicCounter
  * @warning Must be called only for the counters that has been initialised.
  */
 #  define mhd_atomic_counter_deinit(pcnt) \
-        mhd_mutex_destroy_chk (&((pcnt)->lock))
+          mhd_mutex_destroy_chk (&((pcnt)->lock))
 
 /**
  * Atomically increment the value of the counter
  * @param pcnt the pointer to the counter to increment
  */
-#  define mhd_atomic_counter_inc(pcnt)  do { \
-          mhd_mutex_lock_chk (&((pcnt)->lock));     \
-          ++(pcnt->count);                       \
+#  define mhd_atomic_counter_inc(pcnt)  do {   \
+          mhd_mutex_lock_chk (&((pcnt)->lock)); \
+          ++((pcnt)->count);                     \
           mhd_mutex_unlock_chk (&((pcnt)->lock)); } while (0)
 
 /**
@@ -184,7 +265,7 @@ mhd_atomic_counter_get (struct mhd_AtomicCounter *pcnt);
  *          already.
  */
 #  define mhd_atomic_counter_init(pcnt,initial_value) \
-        ((pcnt)->count = (initial_value), (! 0))
+          ((pcnt)->count = (initial_value), (! 0))
 
 /**
  * Deinitialise the counter.
@@ -197,7 +278,7 @@ mhd_atomic_counter_get (struct mhd_AtomicCounter *pcnt);
  * Atomically increment the value of the counter
  * @param pcnt the pointer to the counter to increment
  */
-#  define mhd_atomic_counter_inc(pcnt)  do { ++(pcnt->count); } while (0)
+#  define mhd_atomic_counter_inc(pcnt)  do { ++((pcnt)->count); } while (0)
 
 /**
  * Atomically increment the value of the counter and return the result
@@ -220,6 +301,15 @@ mhd_atomic_counter_get (struct mhd_AtomicCounter *pcnt);
  */
 #  define mhd_atomic_counter_get(pcnt) ((pcnt)->count)
 
+/**
+ * Atomically increment the value of the counter and return the result.
+ * The value is allowed to overflow and get back to zero.
+ * @param pcnt the pointer to the counter to increment
+ * @return the final/resulting counter value
+ */
+#  define mhd_atomic_counter_inc_wrap_get(pcnt) \
+          mhd_atomic_counter_inc_get (pcnt)
+
 #endif /* mhd_ATOMIC_SINGLE_THREAD */
 
 #endif /* ! MHD_ATOMIC_COUNTER_H */
diff --git a/src/mhd2/mhd_daemon.h b/src/mhd2/mhd_daemon.h
index 1b6f7ee..396d948 100644
--- a/src/mhd2/mhd_daemon.h
+++ b/src/mhd2/mhd_daemon.h
@@ -58,6 +58,8 @@
 #  include <sys/epoll.h>
 #endif
 
+#include "mempool_types.h"
+
 #include "mhd_public_api.h"
 
 struct DaemonOptions; /* Forward declaration */
@@ -897,6 +899,11 @@ struct mhd_DaemonConnectionsSettings
    * Connection's memory pool size
    */
   size_t mem_pool_size;
+
+  /**
+   * Memory pool zeroing mode
+   */
+  enum mhd_MemPoolZeroing mem_pool_zeroing;
 };
 
 #ifdef MHD_SUPPORT_UPGRADE
diff --git a/src/mhd2/mhd_reply.h b/src/mhd2/mhd_reply.h
index f255b41..49ced3c 100644
--- a/src/mhd2/mhd_reply.h
+++ b/src/mhd2/mhd_reply.h
@@ -49,7 +49,7 @@ struct MHD_Response; /* forward declaration */
  */
 struct MHD_Reply_Properties
 {
-#ifdef _DEBUG
+#ifndef NDEBUG
   bool set; /**< Indicates that other members are set and valid */
 #endif /* _DEBUG */
   bool use_reply_body_headers; /**< Use reply body-specific headers */
diff --git a/src/mhd2/respond_with_error.c b/src/mhd2/respond_with_error.c
index 9f6e15d..52a0139 100644
--- a/src/mhd2/respond_with_error.c
+++ b/src/mhd2/respond_with_error.c
@@ -35,7 +35,7 @@
 
 #include "mhd_connection.h"
 
-#include "mhd_mempool.h"
+#include "mempool_funcs.h"
 
 #include "response_from.h"
 #include "daemon_logger.h"
diff --git a/src/mhd2/response_funcs.c b/src/mhd2/response_funcs.c
index 150f2b3..f4576dc 100644
--- a/src/mhd2/response_funcs.c
+++ b/src/mhd2/response_funcs.c
@@ -28,13 +28,13 @@
 
 #include "sys_malloc.h"
 
+#include "mhd_assert.h"
 #include "sys_null_macro.h"
 #include "mhd_response.h"
 #include "response_funcs.h"
 #include "mhd_locks.h"
 #include "response_options.h"
 
-
 #include "mhd_atomic_counter.h"
 
 
@@ -117,15 +117,18 @@ mhd_response_check_frozen_freeze (struct MHD_Response 
*restrict response)
 
   if (response->reuse.reusable)
   {
-    need_unlock = true;
     mhd_mutex_lock_chk (&(response->reuse.settings_lock));
-    mhd_assert (1 == mhd_atomic_counter_get (&(response->reuse.counter)));
+    need_unlock = true;
   }
   else
     need_unlock = false;
 
   if (! response->frozen)/* Re-check under the lock */
+  {
+      mhd_assert ((! response->reuse.reusable) || \
+                  (1 == mhd_atomic_counter_get (&(response->reuse.counter))));
     response_set_properties (response);
+  }
 
   if (need_unlock)
     mhd_mutex_unlock_chk (&(response->reuse.settings_lock));
diff --git a/src/mhd2/stream_funcs.c b/src/mhd2/stream_funcs.c
index f6e37ce..3c2c5e1 100644
--- a/src/mhd2/stream_funcs.c
+++ b/src/mhd2/stream_funcs.c
@@ -44,7 +44,7 @@
 #include "mhd_daemon.h"
 #include "mhd_connection.h"
 #include "mhd_response.h"
-#include "mhd_mempool.h"
+#include "mempool_funcs.h"
 #include "mhd_str.h"
 #include "mhd_str_macros.h"
 
@@ -567,9 +567,7 @@ mhd_stream_finish_req_serving (struct MHD_Connection 
*restrict c,
 
     c->conn_reuse = mhd_CONN_KEEPALIVE_POSSIBLE;
     c->stage = mhd_HTTP_STAGE_INIT;
-    c->event_loop_info =
-      (0 == c->read_buffer_offset) ?
-      MHD_EVENT_LOOP_INFO_RECV : MHD_EVENT_LOOP_INFO_PROCESS;
+    c->event_loop_info = MHD_EVENT_LOOP_INFO_RECV; /* Dummy state, real state 
set later */
 
     // TODO: move request reset to special function
     memset (&c->rq, 0, sizeof(c->rq));
diff --git a/src/mhd2/stream_process_reply.c b/src/mhd2/stream_process_reply.c
index c257069..68a7a64 100644
--- a/src/mhd2/stream_process_reply.c
+++ b/src/mhd2/stream_process_reply.c
@@ -335,7 +335,7 @@ setup_reply_properties (struct MHD_Connection *restrict c)
     }
   }
 
-#ifdef _DEBUG
+#ifndef NDEBUG
   c->rp.props.set = true;
 #endif /* _DEBUG */
 }
diff --git a/src/mhd2/stream_process_request.c 
b/src/mhd2/stream_process_request.c
index 32a5fdb..5bdf8d3 100644
--- a/src/mhd2/stream_process_request.c
+++ b/src/mhd2/stream_process_request.c
@@ -56,7 +56,7 @@
 #include "daemon_logger.h"
 #include "mhd_panic.h"
 
-#include "mhd_mempool.h"
+#include "mempool_funcs.h"
 
 #include "request_funcs.h"
 #include "request_get_value.h"
diff --git a/src/tools/perf_replies.c b/src/tools/perf_replies.c
index 31f1ef7..6c713b3 100644
--- a/src/tools/perf_replies.c
+++ b/src/tools/perf_replies.c
@@ -1596,7 +1596,7 @@ static void
 print_perf_warnings (void)
 {
   int newline_needed = 0;
-#if defined (_DEBUG)
+#if !defined(NDEBUG) || defined(_DEBUG)
   fprintf (stderr, "WARNING: Running with debug asserts enabled, "
            "the performance is suboptimal.\n");
   newline_needed |=  ! 0;
@@ -1878,7 +1878,9 @@ run_mhd (void)
   if (1)
   {
     char buf[10];
-    (void) fgets (buf, sizeof(buf), stdin);
+    const char *get_ret;
+    get_ret = fgets (buf, sizeof(buf), stdin);
+    (void) get_ret; /* Mute compiler warning */
   }
   MHD_daemon_destroy (d);
   return 0;

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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