gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r36568 - in libmicrohttpd: . src/include src/microhttpd src


From: gnunet
Subject: [GNUnet-SVN] r36568 - in libmicrohttpd: . src/include src/microhttpd src/testcurl
Date: Sun, 25 Oct 2015 15:33:28 +0100

Author: grothoff
Date: 2015-10-25 15:33:28 +0100 (Sun, 25 Oct 2015)
New Revision: 36568

Modified:
   libmicrohttpd/ChangeLog
   libmicrohttpd/src/include/microhttpd.h
   libmicrohttpd/src/microhttpd/connection.c
   libmicrohttpd/src/microhttpd/connection.h
   libmicrohttpd/src/microhttpd/connection_https.c
   libmicrohttpd/src/microhttpd/daemon.c
   libmicrohttpd/src/testcurl/test_concurrent_stop.c
Log:
-fix assertion failure from race on shutdown and buffer shrinkage with 
pipelining

Modified: libmicrohttpd/ChangeLog
===================================================================
--- libmicrohttpd/ChangeLog     2015-10-25 13:08:17 UTC (rev 36567)
+++ libmicrohttpd/ChangeLog     2015-10-25 14:33:28 UTC (rev 36568)
@@ -1,3 +1,12 @@
+Sun Oct 25 15:29:23 CET 2015
+       Fixing transient resource leak affecting long-lived
+       connections with many keep-alives and HTTP request
+       pipelining under certain circumstances (which reduced
+       the receive window).
+       Fixed assertion failure triggered by a race in
+       thread-per-connection mode on shutdown in rare
+       circumstances. -CG
+
 Mon Oct  5 11:53:52 CEST 2015
        Deduplicate code between digestauth and connection
        parsing logic for URI arguments, shared code moved

Modified: libmicrohttpd/src/include/microhttpd.h
===================================================================
--- libmicrohttpd/src/include/microhttpd.h      2015-10-25 13:08:17 UTC (rev 
36567)
+++ libmicrohttpd/src/include/microhttpd.h      2015-10-25 14:33:28 UTC (rev 
36568)
@@ -130,7 +130,7 @@
  * Current version of the library.
  * 0x01093001 = 1.9.30-1.
  */
-#define MHD_VERSION 0x00094401
+#define MHD_VERSION 0x00094402
 
 /**
  * MHD-internal return code for "YES".

Modified: libmicrohttpd/src/microhttpd/connection.c
===================================================================
--- libmicrohttpd/src/microhttpd/connection.c   2015-10-25 13:08:17 UTC (rev 
36567)
+++ libmicrohttpd/src/microhttpd/connection.c   2015-10-25 14:33:28 UTC (rev 
36568)
@@ -264,8 +264,8 @@
  * @param termination_code termination reason to give
  */
 void
-MHD_connection_close (struct MHD_Connection *connection,
-                      enum MHD_RequestTerminationCode termination_code)
+MHD_connection_close_ (struct MHD_Connection *connection,
+                       enum MHD_RequestTerminationCode termination_code)
 {
   struct MHD_Daemon *daemon;
 
@@ -300,8 +300,8 @@
   if (NULL != emsg)
     MHD_DLOG (connection->daemon, emsg);
 #endif
-  MHD_connection_close (connection,
-                       MHD_REQUEST_TERMINATED_WITH_ERROR);
+  MHD_connection_close_ (connection,
+                         MHD_REQUEST_TERMINATED_WITH_ERROR);
 }
 
 
@@ -368,8 +368,8 @@
       if (NULL != response->crc)
         (void) MHD_mutex_unlock_ (&response->mutex);
       if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret)
-       MHD_connection_close (connection,
-                             MHD_REQUEST_TERMINATED_COMPLETED_OK);
+       MHD_connection_close_ (connection,
+                               MHD_REQUEST_TERMINATED_COMPLETED_OK);
       else
        CONNECTION_CLOSE_ERROR (connection,
                                "Closing connection (stream error)\n");
@@ -1611,8 +1611,8 @@
       /* other side closed connection; RFC 2616, section 8.1.4 suggests
         we should then shutdown ourselves as well. */
       connection->read_closed = MHD_YES;
-      MHD_connection_close (connection,
-                           MHD_REQUEST_TERMINATED_CLIENT_ABORT);
+      MHD_connection_close_ (connection,
+                             MHD_REQUEST_TERMINATED_CLIENT_ABORT);
       return MHD_YES;
     }
   connection->read_buffer_offset += bytes_read;
@@ -1959,8 +1959,8 @@
           /* nothing to do but default action */
           if (MHD_YES == connection->read_closed)
             {
-             MHD_connection_close (connection,
-                                   MHD_REQUEST_TERMINATED_READ_ERROR);
+             MHD_connection_close_ (connection,
+                                     MHD_REQUEST_TERMINATED_READ_ERROR);
               continue;
             }
           break;
@@ -2539,8 +2539,8 @@
               (MHD_NO == keepalive_possible (connection)))
             {
               /* have to close for some reason */
-              MHD_connection_close (connection,
-                                    MHD_REQUEST_TERMINATED_COMPLETED_OK);
+              MHD_connection_close_ (connection,
+                                     MHD_REQUEST_TERMINATED_COMPLETED_OK);
               MHD_pool_destroy (connection->pool);
               connection->pool = NULL;
               connection->read_buffer = NULL;
@@ -2555,7 +2555,7 @@
               connection->read_buffer
                 = MHD_pool_reset (connection->pool,
                                   connection->read_buffer,
-                                  connection->read_buffer_size);
+                                  connection->read_buffer_offset);
             }
          connection->client_aware = MHD_NO;
           connection->client_context = NULL;
@@ -2585,8 +2585,8 @@
   if ( (0 != timeout) &&
        (timeout <= (MHD_monotonic_sec_counter() - connection->last_activity)) )
     {
-      MHD_connection_close (connection,
-                           MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
+      MHD_connection_close_ (connection,
+                             MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
       connection->in_idle = MHD_NO;
       return MHD_YES;
     }

Modified: libmicrohttpd/src/microhttpd/connection.h
===================================================================
--- libmicrohttpd/src/microhttpd/connection.h   2015-10-25 13:08:17 UTC (rev 
36567)
+++ libmicrohttpd/src/microhttpd/connection.h   2015-10-25 14:33:28 UTC (rev 
36568)
@@ -89,8 +89,8 @@
  * @param termination_code termination reason to give
  */
 void
-MHD_connection_close (struct MHD_Connection *connection,
-                     enum MHD_RequestTerminationCode termination_code);
+MHD_connection_close_ (struct MHD_Connection *connection,
+                       enum MHD_RequestTerminationCode termination_code);
 
 
 #if EPOLL_SUPPORT

Modified: libmicrohttpd/src/microhttpd/connection_https.c
===================================================================
--- libmicrohttpd/src/microhttpd/connection_https.c     2015-10-25 13:08:17 UTC 
(rev 36567)
+++ libmicrohttpd/src/microhttpd/connection_https.c     2015-10-25 14:33:28 UTC 
(rev 36568)
@@ -69,8 +69,8 @@
       MHD_DLOG (connection->daemon,
                "Error: received handshake message out of context\n");
 #endif
-      MHD_connection_close (connection,
-                           MHD_REQUEST_TERMINATED_WITH_ERROR);
+      MHD_connection_close_ (connection,
+                             MHD_REQUEST_TERMINATED_WITH_ERROR);
       return MHD_YES;
     }
   return MHD_NO;
@@ -142,8 +142,8 @@
 #endif
   timeout = connection->connection_timeout;
   if ( (timeout != 0) && (timeout <= (MHD_monotonic_sec_counter() - 
connection->last_activity)))
-    MHD_connection_close (connection,
-                         MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
+    MHD_connection_close_ (connection,
+                           MHD_REQUEST_TERMINATED_TIMEOUT_REACHED);
   switch (connection->state)
     {
       /* on newly created connections we might reach here before any reply has 
been received */

Modified: libmicrohttpd/src/microhttpd/daemon.c
===================================================================
--- libmicrohttpd/src/microhttpd/daemon.c       2015-10-25 13:08:17 UTC (rev 
36567)
+++ libmicrohttpd/src/microhttpd/daemon.c       2015-10-25 14:33:28 UTC (rev 
36568)
@@ -135,7 +135,8 @@
               const char *reason)
 {
 #if HAVE_MESSAGES
-  fprintf (stderr, "Fatal error in GNU libmicrohttpd %s:%u: %s\n",
+  fprintf (stderr,
+           "Fatal error in GNU libmicrohttpd %s:%u: %s\n",
           file, line, reason);
 #endif
   abort ();
@@ -994,7 +995,8 @@
          if (0 != (p[0].revents & POLLOUT))
            con->write_handler (con);
          if (0 != (p[0].revents & (POLLERR | POLLHUP)))
-           MHD_connection_close (con, MHD_REQUEST_TERMINATED_WITH_ERROR);
+           MHD_connection_close_ (con,
+                                   MHD_REQUEST_TERMINATED_WITH_ERROR);
          if (MHD_NO == con->idle_handler (con))
            goto exit;
        }
@@ -1009,8 +1011,8 @@
 #endif
 #endif
       if (MHD_CONNECTION_CLOSED != con->state)
-       MHD_connection_close (con,
-                             MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
+       MHD_connection_close_ (con,
+                               MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
       con->idle_handler (con);
     }
 exit:
@@ -4359,8 +4361,8 @@
 {
   struct MHD_Daemon *daemon = pos->daemon;
 
-  MHD_connection_close (pos,
-                       MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
+  MHD_connection_close_ (pos,
+                         MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN);
   if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
     return; /* must let thread to the rest */
   if (pos->connection_timeout == pos->daemon->connection_timeout)
@@ -4398,15 +4400,17 @@
   if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
        (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) )
     MHD_PANIC ("Failed to acquire cleanup mutex\n");
+  if (NULL != daemon->suspended_connections_head)
+    MHD_PANIC ("MHD_stop_daemon() called while we have suspended 
connections.\n");
   for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
     {
       shutdown (pos->socket_fd,
-                (pos->read_closed == MHD_YES) ? SHUT_WR : SHUT_RDWR);
+                (MHD_YES == pos->read_closed) ? SHUT_WR : SHUT_RDWR);
 #if MHD_WINSOCK_SOCKETS
       if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
            (MHD_INVALID_PIPE_ != daemon->wpipe[1]) &&
            (1 != MHD_pipe_write_ (daemon->wpipe[1], "e", 1)) )
-        MHD_PANIC ("failed to signal shutdown via pipe");
+        MHD_PANIC ("Failed to signal shutdown via pipe");
 #endif
     }
   if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
@@ -4413,20 +4417,33 @@
        (MHD_YES != MHD_mutex_unlock_ (&daemon->cleanup_connection_mutex)) )
     MHD_PANIC ("Failed to release cleanup mutex\n");
 
-  /* now, collect threads from thread pool */
+  /* now, collect per-connection threads */
   if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
     {
-      for (pos = daemon->connections_head; NULL != pos; pos = pos->next)
-       {
-         if (0 != MHD_join_thread_ (pos->pid))
-           MHD_PANIC ("Failed to join a thread\n");
-         pos->thread_joined = MHD_YES;
-       }
+      pos = daemon->connections_head;
+      while (NULL != pos)
+      {
+        if (MHD_YES != pos->thread_joined)
+          {
+            if (0 != MHD_join_thread_ (pos->pid))
+              MHD_PANIC ("Failed to join a thread\n");
+            pos->thread_joined = MHD_YES;
+            /* The thread may have concurrently modified the DLL,
+               need to restart from the beginning */
+            pos = daemon->connections_head;
+            continue;
+          }
+        pos = pos->next;
+      }
     }
-
   /* now that we're alone, move everyone to cleanup */
   while (NULL != (pos = daemon->connections_head))
+  {
+    if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
+         (MHD_YES != pos->thread_joined) )
+      MHD_PANIC ("Failed to join a thread\n");
     close_connection (pos);
+  }
   MHD_cleanup_connections (daemon);
 }
 
@@ -4478,7 +4495,7 @@
   /* Prepare workers for shutdown */
   if (NULL != daemon->worker_pool)
     {
-      /* MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to 
check */
+      /* #MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to 
check */
       for (i = 0; i < daemon->worker_pool_size; ++i)
        {
          daemon->worker_pool[i].shutdown = MHD_YES;
@@ -4556,9 +4573,9 @@
   else
     {
       /* clean up master threads */
-      if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
-         ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))
-          && (0 == daemon->worker_pool_size)))
+      if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
+           ( (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) &&
+             (0 == daemon->worker_pool_size) ) )
        {
          if (0 != MHD_join_thread_ (daemon->pid))
            {
@@ -4676,7 +4693,8 @@
  * @ingroup logging
  */
 void
-MHD_set_panic_func (MHD_PanicCallback cb, void *cls)
+MHD_set_panic_func (MHD_PanicCallback cb,
+                    void *cls)
 {
   mhd_panic = cb;
   mhd_panic_cls = cls;
@@ -4825,13 +4843,14 @@
 #if defined(MHD_USE_POSIX_THREADS)
 GCRY_THREAD_OPTION_PTHREAD_IMPL;
 #elif defined(MHD_W32_MUTEX_)
-static int gcry_w32_mutex_init (void **ppmtx)
+
+static int
+gcry_w32_mutex_init (void **ppmtx)
 {
   *ppmtx = malloc (sizeof (MHD_mutex_));
 
   if (NULL == *ppmtx)
     return ENOMEM;
-
   if (MHD_YES != MHD_mutex_create_ ((MHD_mutex_*)*ppmtx))
     {
       free (*ppmtx);
@@ -4841,14 +4860,31 @@
 
   return 0;
 }
-static int gcry_w32_mutex_destroy (void **ppmtx)
-  { int res = (MHD_YES == MHD_mutex_destroy_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1;
-    free (*ppmtx); return res; }
-static int gcry_w32_mutex_lock (void **ppmtx)
-  { return (MHD_YES == MHD_mutex_lock_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1; }
-static int gcry_w32_mutex_unlock (void **ppmtx)
-  { return (MHD_YES == MHD_mutex_unlock_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1; }
 
+
+static int
+gcry_w32_mutex_destroy (void **ppmtx)
+{
+  int res = (MHD_YES == MHD_mutex_destroy_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1;
+  free (*ppmtx);
+  return res;
+}
+
+
+static int
+gcry_w32_mutex_lock (void **ppmtx)
+{
+  return (MHD_YES == MHD_mutex_lock_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1;
+}
+
+
+static int
+gcry_w32_mutex_unlock (void **ppmtx)
+{
+  return (MHD_YES == MHD_mutex_unlock_ ((MHD_mutex_*)*ppmtx)) ? 0 : 1;
+}
+
+
 static struct gcry_thread_cbs gcry_threads_w32 = {
   (GCRY_THREAD_OPTION_USER | (GCRY_THREAD_OPTION_VERSION << 8)),
   NULL, gcry_w32_mutex_init, gcry_w32_mutex_destroy,
@@ -4862,7 +4898,8 @@
 /**
  * Initialize do setup work.
  */
-void MHD_init(void)
+void
+MHD_init(void)
 {
   mhd_panic = &mhd_panic_std;
   mhd_panic_cls = NULL;
@@ -4895,7 +4932,8 @@
 }
 
 
-void MHD_fini(void)
+void
+MHD_fini(void)
 {
 #if HTTPS_SUPPORT
   gnutls_global_deinit ();

Modified: libmicrohttpd/src/testcurl/test_concurrent_stop.c
===================================================================
--- libmicrohttpd/src/testcurl/test_concurrent_stop.c   2015-10-25 13:08:17 UTC 
(rev 36567)
+++ libmicrohttpd/src/testcurl/test_concurrent_stop.c   2015-10-25 14:33:28 UTC 
(rev 36568)
@@ -68,6 +68,7 @@
   return size * nmemb;
 }
 
+
 static int
 ahc_echo (void *cls,
           struct MHD_Connection *connection,
@@ -74,7 +75,8 @@
           const char *url,
           const char *method,
           const char *version,
-          const char *upload_data, size_t *upload_data_size,
+          const char *upload_data,
+          size_t *upload_data_size,
           void **unused)
 {
   static int ptr;
@@ -166,7 +168,8 @@
 
 
 static int
-testMultithreadedGet (int port, int poll_flag)
+testMultithreadedGet (int port,
+                      int poll_flag)
 {
   struct MHD_Daemon *d;
   pid_t p;
@@ -184,7 +187,8 @@
 
 
 static int
-testMultithreadedPoolGet (int port, int poll_flag)
+testMultithreadedPoolGet (int port,
+                          int poll_flag)
 {
   struct MHD_Daemon *d;
   pid_t p;




reply via email to

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