XXX under some circumstances not understood, children can get stuck * in start_threads forever trying to take over slots which will * never be cleaned up; for now there is an APLOG_DEBUG message issued * every so often when this condition occurs */
| 2460 | * every so often when this condition occurs |
| 2461 | */ |
| 2462 | static void *APR_THREAD_FUNC start_threads(apr_thread_t * thd, void *dummy) |
| 2463 | { |
| 2464 | thread_starter *ts = dummy; |
| 2465 | apr_thread_t **threads = ts->threads; |
| 2466 | apr_threadattr_t *thread_attr = ts->threadattr; |
| 2467 | int my_child_num = ts->child_num_arg; |
| 2468 | proc_info *my_info; |
| 2469 | apr_status_t rv; |
| 2470 | int threads_created = 0; |
| 2471 | int listener_started = 0; |
| 2472 | int prev_threads_created; |
| 2473 | int loops, i; |
| 2474 | |
| 2475 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, APLOGNO(02471) |
| 2476 | "start_threads: Using %s (%swakeable)", |
| 2477 | apr_pollset_method_name(event_pollset), |
| 2478 | listener_is_wakeable ? "" : "not "); |
| 2479 | |
| 2480 | loops = prev_threads_created = 0; |
| 2481 | while (1) { |
| 2482 | /* threads_per_child does not include the listener thread */ |
| 2483 | for (i = 0; i < threads_per_child; i++) { |
| 2484 | int status = |
| 2485 | ap_scoreboard_image->servers[my_child_num][i].status; |
| 2486 | |
| 2487 | if (status != SERVER_DEAD) { |
| 2488 | continue; |
| 2489 | } |
| 2490 | |
| 2491 | my_info = (proc_info *) ap_malloc(sizeof(proc_info)); |
| 2492 | my_info->pslot = my_child_num; |
| 2493 | my_info->tslot = i; |
| 2494 | |
| 2495 | /* We are creating threads right now */ |
| 2496 | ap_update_child_status_from_indexes(my_child_num, i, |
| 2497 | SERVER_STARTING, NULL); |
| 2498 | /* We let each thread update its own scoreboard entry. This is |
| 2499 | * done because it lets us deal with tid better. |
| 2500 | */ |
| 2501 | rv = ap_thread_create(&threads[i], thread_attr, |
| 2502 | worker_thread, my_info, pruntime); |
| 2503 | if (rv != APR_SUCCESS) { |
| 2504 | ap_log_error(APLOG_MARK, APLOG_ALERT, rv, ap_server_conf, |
| 2505 | APLOGNO(03104) |
| 2506 | "ap_thread_create: unable to create worker thread"); |
| 2507 | /* let the parent decide how bad this really is */ |
| 2508 | clean_child_exit(APEXIT_CHILDSICK); |
| 2509 | } |
| 2510 | threads_created++; |
| 2511 | } |
| 2512 | |
| 2513 | /* Start the listener only when there are workers available */ |
| 2514 | if (!listener_started && threads_created) { |
| 2515 | create_listener_thread(ts); |
| 2516 | listener_started = 1; |
| 2517 | } |
| 2518 | |
| 2519 |
nothing calls this directly
no test coverage detected