}
-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.
HANDLE *child_handles;
int listener_started = 0;
int threads_created = 0;
- int watch_thread;
int time_remains;
int cld;
DWORD tid;
* (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;
}
}