소스 검색

add test logic to check that callbacks are invoked properly (and from the right thread), fix when callbacks are invoked where issues exist

Christian Grothoff 9 년 전
부모
커밋
dc9b5154ae
4개의 변경된 파일147개의 추가작업 그리고 40개의 파일을 삭제
  1. 52 40
      src/microhttpd/daemon.c
  2. 8 0
      src/microhttpd/test_upgrade.c
  3. 84 0
      src/microhttpd/test_upgrade_common.c
  4. 3 0
      src/microhttpd/test_upgrade_ssl.c

+ 52 - 40
src/microhttpd/daemon.c

@@ -3671,6 +3671,39 @@ MHD_run (struct MHD_Daemon *daemon)
 }
 
 
+/**
+ * Close the given connection, remove it from all of its
+ * DLLs and move it into the cleanup queue.
+ *
+ * @param pos connection to move to cleanup
+ */
+static void
+close_connection (struct MHD_Connection *pos)
+{
+  struct MHD_Daemon *daemon = pos->daemon;
+
+  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)
+    XDLL_remove (daemon->normal_timeout_head,
+		 daemon->normal_timeout_tail,
+		 pos);
+  else
+    XDLL_remove (daemon->manual_timeout_head,
+		 daemon->manual_timeout_tail,
+		 pos);
+  DLL_remove (daemon->connections_head,
+	      daemon->connections_tail,
+	      pos);
+  pos->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
+  DLL_insert (daemon->cleanup_head,
+	      daemon->cleanup_tail,
+	      pos);
+}
+
+
 /**
  * Thread that runs the select loop until the daemon
  * is explicitly shut down.
@@ -3682,6 +3715,7 @@ static MHD_THRD_RTRN_TYPE_ MHD_THRD_CALL_SPEC_
 MHD_select_thread (void *cls)
 {
   struct MHD_Daemon *daemon = cls;
+  struct MHD_Connection *pos;
 
   while (MHD_YES != daemon->shutdown)
     {
@@ -3695,6 +3729,17 @@ MHD_select_thread (void *cls)
 	MHD_select (daemon, MHD_YES);
       MHD_cleanup_connections (daemon);
     }
+
+  /* give resumed formerly suspended connections a chance to
+     be included in the cleanup */
+  resume_suspended_connections (daemon);
+  /* run clean up in this thread as well */
+  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
+    {
+      /* We did everything in this thread, so also the clean up */
+      while (NULL != (pos = daemon->connections_head))
+        close_connection (pos);
+    }
   return (MHD_THRD_RTRN_TYPE_)0;
 }
 
@@ -5040,11 +5085,11 @@ MHD_start_daemon_va (unsigned int flags,
             }
 
           /* Spawn the worker thread */
-          if (! MHD_create_named_thread_(&d->pid,
-                                         "MHD-worker",
-                                         daemon->thread_stack_size,
-                                         &MHD_select_thread,
-                                         d))
+          if (! MHD_create_named_thread_ (&d->pid,
+                                          "MHD-worker",
+                                          daemon->thread_stack_size,
+                                          &MHD_select_thread,
+                                          d))
             {
 #ifdef HAVE_MESSAGES
               MHD_DLOG (daemon,
@@ -5127,39 +5172,6 @@ thread_failed:
 }
 
 
-/**
- * Close the given connection, remove it from all of its
- * DLLs and move it into the cleanup queue.
- *
- * @param pos connection to move to cleanup
- */
-static void
-close_connection (struct MHD_Connection *pos)
-{
-  struct MHD_Daemon *daemon = pos->daemon;
-
-  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)
-    XDLL_remove (daemon->normal_timeout_head,
-		 daemon->normal_timeout_tail,
-		 pos);
-  else
-    XDLL_remove (daemon->manual_timeout_head,
-		 daemon->manual_timeout_tail,
-		 pos);
-  DLL_remove (daemon->connections_head,
-	      daemon->connections_tail,
-	      pos);
-  pos->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
-  DLL_insert (daemon->cleanup_head,
-	      daemon->cleanup_tail,
-	      pos);
-}
-
-
 /**
  * Close all connections for the daemon; must only be called after
  * all of the threads have been joined and there is no more concurrent
@@ -5347,7 +5359,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
 	      if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "e"))
 		MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel."));
 	    }
-	  if (!MHD_join_thread_ (daemon->worker_pool[i].pid))
+	  if (! MHD_join_thread_ (daemon->worker_pool[i].pid))
             MHD_PANIC (_("Failed to join a thread\n"));
 	  close_all_connections (&daemon->worker_pool[i]);
 	  MHD_mutex_destroy_chk_ (&daemon->worker_pool[i].cleanup_connection_mutex);
@@ -5377,7 +5389,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon)
            ( (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) &&
              (0 == daemon->worker_pool_size) ) )
 	{
-	  if (!MHD_join_thread_ (daemon->pid))
+	  if (! MHD_join_thread_ (daemon->pid))
 	    {
 	      MHD_PANIC (_("Failed to join a thread\n"));
 	    }

+ 8 - 0
src/microhttpd/test_upgrade.c

@@ -63,6 +63,9 @@ test_upgrade (int flags,
                         1080,
                         NULL, NULL,
                         &ahc_upgrade, NULL,
+                        MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL,
+                        MHD_OPTION_NOTIFY_COMPLETED, &notify_completed_cb, NULL,
+                        MHD_OPTION_NOTIFY_CONNECTION, &notify_connection_cb, NULL,
                         MHD_OPTION_THREAD_POOL_SIZE, pool,
                         MHD_OPTION_END);
   if (NULL == d)
@@ -101,6 +104,8 @@ main (int argc,
   int error_count = 0;
 
   /* try external select */
+#if 0
+
   error_count += test_upgrade (0,
                                0);
 #ifdef EPOLL_SUPPORT
@@ -117,6 +122,9 @@ main (int argc,
   /* Test different event loops, with and without thread pool */
   error_count += test_upgrade (MHD_USE_SELECT_INTERNALLY,
                                0);
+
+#endif
+
   error_count += test_upgrade (MHD_USE_SELECT_INTERNALLY,
                                2);
 #ifdef HAVE_POLL

+ 84 - 0
src/microhttpd/test_upgrade_common.c

@@ -46,6 +46,88 @@ static pthread_t pt_client;
 static int done;
 
 
+static void
+notify_completed_cb (void *cls,
+                     struct MHD_Connection *connection,
+                     void **con_cls,
+                     enum MHD_RequestTerminationCode toe)
+{
+  if ( (toe != MHD_REQUEST_TERMINATED_COMPLETED_OK) &&
+       (toe != MHD_REQUEST_TERMINATED_CLIENT_ABORT) &&
+       (toe != MHD_REQUEST_TERMINATED_DAEMON_SHUTDOWN) )
+    abort ();
+  if (((long) *con_cls) != (long) pthread_self ())
+    abort ();
+  *con_cls = NULL;
+}
+
+
+/**
+ * Logging callback.
+ *
+ * @param cls logging closure (NULL)
+ * @param uri access URI
+ * @param connection connection handle
+ * @return #TEST_PTR
+ */
+static void *
+log_cb (void *cls,
+        const char *uri,
+        struct MHD_Connection *connection)
+{
+  if (0 != strcmp (uri,
+                   "/"))
+    abort ();
+  return (void *) (long) pthread_self ();
+}
+
+
+/**
+ * Function to check that MHD properly notifies about starting
+ * and stopping.
+ *
+ * @param cls client-defined closure
+ * @param connection connection handle
+ * @param socket_context socket-specific pointer where the
+ *                       client can associate some state specific
+ *                       to the TCP connection; note that this is
+ *                       different from the "con_cls" which is per
+ *                       HTTP request.  The client can initialize
+ *                       during #MHD_CONNECTION_NOTIFY_STARTED and
+ *                       cleanup during #MHD_CONNECTION_NOTIFY_CLOSED
+ *                       and access in the meantime using
+ *                       #MHD_CONNECTION_INFO_SOCKET_CONTEXT.
+ * @param toe reason for connection notification
+ * @see #MHD_OPTION_NOTIFY_CONNECTION
+ * @ingroup request
+ */
+static void
+notify_connection_cb (void *cls,
+                      struct MHD_Connection *connection,
+                      void **socket_context,
+                      enum MHD_ConnectionNotificationCode toe)
+{
+  static int started;
+
+  switch (toe)
+  {
+  case MHD_CONNECTION_NOTIFY_STARTED:
+    if (MHD_NO != started)
+      abort ();
+    started = MHD_YES;
+    *socket_context = &started;
+    break;
+  case MHD_CONNECTION_NOTIFY_CLOSED:
+    if (MHD_YES != started)
+      abort ();
+    if (&started != *socket_context)
+      abort ();
+    *socket_context = NULL;
+    started = MHD_NO;
+    break;
+  }
+}
+
 
 /**
  * Change socket to non-blocking.
@@ -354,6 +436,8 @@ ahc_upgrade (void *cls,
   struct MHD_Response *resp;
   int ret;
 
+  if (((long) *con_cls) != (long) pthread_self ())
+    abort ();
   resp = MHD_create_response_for_upgrade (&upgrade_cb,
                                           NULL);
   MHD_add_response_header (resp,

+ 3 - 0
src/microhttpd/test_upgrade_ssl.c

@@ -117,6 +117,9 @@ test_upgrade (int flags,
                         1080,
                         NULL, NULL,
                         &ahc_upgrade, NULL,
+                        MHD_OPTION_URI_LOG_CALLBACK, &log_cb, NULL,
+                        MHD_OPTION_NOTIFY_COMPLETED, &notify_completed_cb, NULL,
+                        MHD_OPTION_NOTIFY_CONNECTION, &notify_connection_cb, NULL,
                         MHD_OPTION_HTTPS_MEM_KEY, srv_signed_key_pem,
                         MHD_OPTION_HTTPS_MEM_CERT, srv_signed_cert_pem,
                         MHD_OPTION_THREAD_POOL_SIZE, pool,