Lines 815-828
Link Here
|
815 |
} |
815 |
} |
816 |
} |
816 |
} |
817 |
|
817 |
|
818 |
|
|
|
819 |
void child_main(apr_pool_t *pconf) |
818 |
void child_main(apr_pool_t *pconf) |
820 |
{ |
819 |
{ |
|
|
820 |
char pool_tag[32]; |
821 |
static int child_count = 0; |
822 |
apr_pool_t *private_pchild; |
821 |
apr_status_t status; |
823 |
apr_status_t status; |
822 |
apr_hash_t *ht; |
|
|
823 |
ap_listen_rec *lr; |
824 |
ap_listen_rec *lr; |
824 |
HANDLE child_events[2]; |
825 |
HANDLE child_events[2]; |
825 |
HANDLE *child_handles; |
826 |
HANDLE *child_handles; |
|
|
827 |
HANDLE *sb_assignments; |
826 |
int listener_started = 0; |
828 |
int listener_started = 0; |
827 |
int threads_created = 0; |
829 |
int threads_created = 0; |
828 |
int watch_thread; |
830 |
int watch_thread; |
Lines 832-842
Link Here
|
832 |
int rv; |
834 |
int rv; |
833 |
int i; |
835 |
int i; |
834 |
|
836 |
|
835 |
apr_pool_create(&pchild, pconf); |
837 |
apr_pool_create(&private_pchild, pconf); |
836 |
apr_pool_tag(pchild, "pchild"); |
838 |
sprintf(pool_tag, "pchild_%d", child_count++); |
|
|
839 |
apr_pool_tag(private_pchild, pool_tag); |
840 |
pchild = private_pchild; // Share into global context |
837 |
|
841 |
|
838 |
ap_run_child_init(pchild, ap_server_conf); |
842 |
ap_run_child_init(private_pchild, ap_server_conf); |
839 |
ht = apr_hash_make(pchild); |
|
|
840 |
|
843 |
|
841 |
/* Initialize the child_events */ |
844 |
/* Initialize the child_events */ |
842 |
max_requests_per_child_event = CreateEvent(NULL, TRUE, FALSE, NULL); |
845 |
max_requests_per_child_event = CreateEvent(NULL, TRUE, FALSE, NULL); |
Lines 850-856
Link Here
|
850 |
|
853 |
|
851 |
allowed_globals.jobsemaphore = CreateSemaphore(NULL, 0, 1000000, NULL); |
854 |
allowed_globals.jobsemaphore = CreateSemaphore(NULL, 0, 1000000, NULL); |
852 |
apr_thread_mutex_create(&allowed_globals.jobmutex, |
855 |
apr_thread_mutex_create(&allowed_globals.jobmutex, |
853 |
APR_THREAD_MUTEX_DEFAULT, pchild); |
856 |
APR_THREAD_MUTEX_DEFAULT, private_pchild); |
854 |
|
857 |
|
855 |
/* |
858 |
/* |
856 |
* Wait until we have permission to start accepting connections. |
859 |
* Wait until we have permission to start accepting connections. |
Lines 876-882
Link Here
|
876 |
NULL, |
879 |
NULL, |
877 |
0, |
880 |
0, |
878 |
0); /* CONCURRENT ACTIVE THREADS */ |
881 |
0); /* CONCURRENT ACTIVE THREADS */ |
879 |
apr_thread_mutex_create(&qlock, APR_THREAD_MUTEX_DEFAULT, pchild); |
882 |
apr_thread_mutex_create(&qlock, APR_THREAD_MUTEX_DEFAULT, private_pchild); |
880 |
qwait_event = CreateEvent(NULL, TRUE, FALSE, NULL); |
883 |
qwait_event = CreateEvent(NULL, TRUE, FALSE, NULL); |
881 |
if (!qwait_event) { |
884 |
if (!qwait_event) { |
882 |
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf, |
885 |
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf, |
Lines 890-897
Link Here
|
890 |
*/ |
893 |
*/ |
891 |
ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf, |
894 |
ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf, |
892 |
"Child %d: Starting %d worker threads.", my_pid, ap_threads_per_child); |
895 |
"Child %d: Starting %d worker threads.", my_pid, ap_threads_per_child); |
893 |
child_handles = (HANDLE) apr_pcalloc(pchild, ap_threads_per_child * sizeof(int)); |
896 |
child_handles = (HANDLE) apr_pcalloc(private_pchild, ap_threads_per_child * sizeof(int)); |
894 |
apr_thread_mutex_create(&child_lock, APR_THREAD_MUTEX_DEFAULT, pchild); |
897 |
sb_assignments = (HANDLE) apr_pcalloc(private_pchild, ap_threads_per_child * sizeof(int)); |
|
|
898 |
apr_thread_mutex_create(&child_lock, APR_THREAD_MUTEX_DEFAULT, private_pchild); |
895 |
|
899 |
|
896 |
while (1) { |
900 |
while (1) { |
897 |
for (i = 0; i < ap_threads_per_child; i++) { |
901 |
for (i = 0; i < ap_threads_per_child; i++) { |
Lines 901-908
Link Here
|
901 |
continue; |
905 |
continue; |
902 |
} |
906 |
} |
903 |
ap_update_child_status_from_indexes(0, i, SERVER_STARTING, NULL); |
907 |
ap_update_child_status_from_indexes(0, i, SERVER_STARTING, NULL); |
904 |
child_handles[i] = (HANDLE) _beginthreadex(NULL, 0, worker_main, |
908 |
|
905 |
(void *) i, 0, &tid); |
909 |
child_handles[i] = (HANDLE) _beginthreadex(NULL, 0, worker_main, (void *) i, 0, &tid); |
|
|
910 |
|
911 |
/* |
912 |
* Save the score board index in the sb_assignments array keyed to the thread handle. |
913 |
* We need this when cleaning up threads down below... |
914 |
*/ |
915 |
sb_assignments[i] = child_handles[i]; |
916 |
|
906 |
if (child_handles[i] == 0) { |
917 |
if (child_handles[i] == 0) { |
907 |
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf, |
918 |
ap_log_error(APLOG_MARK, APLOG_CRIT, apr_get_os_error(), ap_server_conf, |
908 |
"Child %d: _beginthreadex failed. Unable to create all worker threads. " |
919 |
"Child %d: _beginthreadex failed. Unable to create all worker threads. " |
Lines 912-925
Link Here
|
912 |
goto shutdown; |
923 |
goto shutdown; |
913 |
} |
924 |
} |
914 |
threads_created++; |
925 |
threads_created++; |
915 |
/* Save the score board index in ht keyed to the thread handle. We need this |
|
|
916 |
* when cleaning up threads down below... |
917 |
*/ |
918 |
apr_thread_mutex_lock(child_lock); |
919 |
score_idx = apr_pcalloc(pchild, sizeof(int)); |
920 |
*score_idx = i; |
921 |
apr_hash_set(ht, &child_handles[i], sizeof(HANDLE), score_idx); |
922 |
apr_thread_mutex_unlock(child_lock); |
923 |
} |
926 |
} |
924 |
/* Start the listener only when workers are available */ |
927 |
/* Start the listener only when workers are available */ |
925 |
if (!listener_started && threads_created) { |
928 |
if (!listener_started && threads_created) { |
Lines 1141-1152
Link Here
|
1141 |
my_pid, threads_created); |
1144 |
my_pid, threads_created); |
1142 |
} |
1145 |
} |
1143 |
for (i = 0; i < threads_created; i++) { |
1146 |
for (i = 0; i < threads_created; i++) { |
1144 |
int *score_idx; |
1147 |
int score_idx; |
|
|
1148 |
|
1145 |
TerminateThread(child_handles[i], 1); |
1149 |
TerminateThread(child_handles[i], 1); |
1146 |
CloseHandle(child_handles[i]); |
1150 |
CloseHandle(child_handles[i]); |
|
|
1151 |
|
1147 |
/* Reset the scoreboard entry for the thread we just whacked */ |
1152 |
/* Reset the scoreboard entry for the thread we just whacked */ |
1148 |
score_idx = apr_hash_get(ht, &child_handles[i], sizeof(HANDLE)); |
1153 |
for (score_idx=0; score_idx<ap_threads_per_child; score_idx++) |
1149 |
ap_update_child_status_from_indexes(0, *score_idx, SERVER_DEAD, NULL); |
1154 |
if (sb_assignments[score_idx] == child_handles[i]) break; // Found it! |
|
|
1155 |
|
1156 |
if (score_idx == ap_threads_per_child) { |
1157 |
ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf, |
1158 |
"Child %d: Did not find scoreboard entry for thread 0x%08X.", |
1159 |
my_pid, child_handles[i]); |
1160 |
} |
1161 |
else ap_update_child_status_from_indexes(0, score_idx, SERVER_DEAD, NULL); |
1150 |
} |
1162 |
} |
1151 |
ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf, |
1163 |
ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf, |
1152 |
"Child %d: All worker threads have exited.", my_pid); |
1164 |
"Child %d: All worker threads have exited.", my_pid); |
Lines 1160-1166
Link Here
|
1160 |
CloseHandle(qwait_event); |
1172 |
CloseHandle(qwait_event); |
1161 |
} |
1173 |
} |
1162 |
|
1174 |
|
1163 |
apr_pool_destroy(pchild); |
1175 |
apr_pool_destroy(private_pchild); |
1164 |
CloseHandle(exit_event); |
1176 |
CloseHandle(exit_event); |
1165 |
} |
1177 |
} |
1166 |
|
1178 |
|