]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
mpm_winnt: Simplify the shutdown code that was waiting for multiple worker
authorEvgeny Kotkov <kotkov@apache.org>
Tue, 11 Jul 2017 16:51:09 +0000 (16:51 +0000)
committerEvgeny Kotkov <kotkov@apache.org>
Tue, 11 Jul 2017 16:51:09 +0000 (16:51 +0000)
thread handles in batches.

Starting from r1801636, there is no difference between ending the wait with
one or multiple remaining threads.  This is because we terminate the process
if at least one thread is still active when we hit a timeout.

Therefore, instead of making an effort to evenly distribute and batch the
handles with WaitForMultipleObjects(), we could just start from one end,
and wait for one thread handle at a time.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1801637 13f79535-47bb-0310-9956-ffa450edef68

server/mpm/winnt/child.c

index e2d64c50c42b674fc3fb550038b3663dcc74e440..7cbaf81f4fdcc3e967976a1ad357c9ca50622691 100644 (file)
@@ -841,18 +841,6 @@ static DWORD __stdcall worker_main(void *thread_num_val)
 }
 
 
-static void cleanup_thread(HANDLE *handles, int *thread_cnt,
-                           int thread_to_clean)
-{
-    int i;
-
-    CloseHandle(handles[thread_to_clean]);
-    for (i = thread_to_clean; i < ((*thread_cnt) - 1); i++)
-        handles[i] = handles[i + 1];
-    (*thread_cnt)--;
-}
-
-
 /*
  * child_main()
  * Entry point for the main control thread for the child process.
@@ -904,7 +892,6 @@ void child_main(apr_pool_t *pconf, DWORD parent_pid)
     HANDLE *child_handles;
     int listener_started = 0;
     int threads_created = 0;
-    int watch_thread;
     int time_remains;
     int cld;
     DWORD tid;
@@ -1199,64 +1186,35 @@ void child_main(apr_pool_t *pconf, DWORD parent_pid)
      * (no more than the global server timeout period which
      * we track in msec remaining).
      */
-    watch_thread = 0;
     time_remains = (int)(ap_server_conf->timeout / APR_TIME_C(1000));
 
     while (threads_created)
     {
-        int nFailsafe = MAXIMUM_WAIT_OBJECTS;
+        HANDLE handle = child_handles[threads_created - 1];
         DWORD dwRet;
 
-        /* Every time we roll over to wait on the first group
-         * of MAXIMUM_WAIT_OBJECTS threads, take a breather,
-         * and infrequently update the error log.
-         */
-        if (watch_thread >= threads_created) {
-            if ((time_remains -= 100) < 0)
-                break;
-
-            /* Every 30 seconds give an update */
-            if ((time_remains % 30000) == 0) {
-                ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS,
-                             ap_server_conf, APLOGNO(00362)
-                             "Child: Waiting %d more seconds "
-                             "for %d worker threads to finish.",
-                             time_remains / 1000, threads_created);
-            }
-            /* We'll poll from the top, 10 times per second */
-            Sleep(100);
-            watch_thread = 0;
-        }
-
-        /* Fairness, on each iteration we will pick up with the thread
-         * after the one we just removed, even if it's a single thread.
-         * We don't block here.
-         */
-        dwRet = WaitForMultipleObjects(min(threads_created - watch_thread,
-                                           MAXIMUM_WAIT_OBJECTS),
-                                       child_handles + watch_thread, 0, 0);
-
-        if (dwRet == WAIT_FAILED) {
+        if (time_remains < 0)
             break;
+        /* Every 30 seconds give an update */
+        if ((time_remains % 30000) == 0) {
+            ap_log_error(APLOG_MARK, APLOG_NOTICE, APR_SUCCESS,
+                         ap_server_conf, APLOGNO(00362)
+                         "Child: Waiting %d more seconds "
+                         "for %d worker threads to finish.",
+                         time_remains / 1000, threads_created);
         }
+
+        dwRet = WaitForSingleObject(handle, 100);
+        time_remains -= 100;
         if (dwRet == WAIT_TIMEOUT) {
-            /* none ready */
-            watch_thread += MAXIMUM_WAIT_OBJECTS;
-            continue;
+            /* Keep waiting */
         }
-        else if (dwRet >= WAIT_ABANDONED_0) {
-            /* We just got the ownership of the object, which
-             * should happen at most MAXIMUM_WAIT_OBJECTS times.
-             * It does NOT mean that the object is signaled.
-             */
-            if ((nFailsafe--) < 1)
-                break;
+        else if (dwRet == WAIT_OBJECT_0) {
+            CloseHandle(handle);
+            threads_created--;
         }
         else {
-            watch_thread += (dwRet - WAIT_OBJECT_0);
-            if (watch_thread >= threads_created)
-                break;
-            cleanup_thread(child_handles, &threads_created, watch_thread);
+            break;
         }
     }