| 3129 | } |
| 3130 | |
| 3131 | static void server_main_loop(int remaining_children_to_start) |
| 3132 | { |
| 3133 | int num_buckets = retained->mpm->num_buckets; |
| 3134 | int max_daemon_used = 0; |
| 3135 | int successive_kills = 0; |
| 3136 | int child_slot; |
| 3137 | apr_exit_why_e exitwhy; |
| 3138 | int status, processed_status; |
| 3139 | apr_proc_t pid; |
| 3140 | int i; |
| 3141 | |
| 3142 | while (!retained->mpm->restart_pending && !retained->mpm->shutdown_pending) { |
| 3143 | ap_wait_or_timeout(&exitwhy, &status, &pid, pconf, ap_server_conf); |
| 3144 | |
| 3145 | if (pid.pid != -1) { |
| 3146 | processed_status = ap_process_child_status(&pid, exitwhy, status); |
| 3147 | child_slot = ap_find_child_by_pid(&pid); |
| 3148 | if (processed_status == APEXIT_CHILDFATAL) { |
| 3149 | /* fix race condition found in PR 39311 |
| 3150 | * A child created at the same time as a graceful happens |
| 3151 | * can find the lock missing and create a fatal error. |
| 3152 | * It is not fatal for the last generation to be in this state. |
| 3153 | */ |
| 3154 | if (child_slot < 0 |
| 3155 | || ap_get_scoreboard_process(child_slot)->generation |
| 3156 | == retained->mpm->my_generation) { |
| 3157 | retained->mpm->shutdown_pending = 1; |
| 3158 | child_fatal = 1; |
| 3159 | /* |
| 3160 | * total_daemons counting will be off now, but as we |
| 3161 | * are shutting down, that is not an issue anymore. |
| 3162 | */ |
| 3163 | return; |
| 3164 | } |
| 3165 | else { |
| 3166 | ap_log_error(APLOG_MARK, APLOG_WARNING, 0, ap_server_conf, APLOGNO(00487) |
| 3167 | "Ignoring fatal error in child of previous " |
| 3168 | "generation (pid %ld).", |
| 3169 | (long)pid.pid); |
| 3170 | retained->sick_child_detected = 1; |
| 3171 | } |
| 3172 | } |
| 3173 | else if (processed_status == APEXIT_CHILDSICK) { |
| 3174 | /* tell perform_idle_server_maintenance to check into this |
| 3175 | * on the next timer pop |
| 3176 | */ |
| 3177 | retained->sick_child_detected = 1; |
| 3178 | } |
| 3179 | /* non-fatal death... note that it's gone in the scoreboard. */ |
| 3180 | if (child_slot >= 0) { |
| 3181 | event_note_child_stopped(child_slot, 0, 0); |
| 3182 | |
| 3183 | if (processed_status == APEXIT_CHILDSICK) { |
| 3184 | /* resource shortage, minimize the fork rate */ |
| 3185 | retained->idle_spawn_rate[child_slot % num_buckets] = 1; |
| 3186 | } |
| 3187 | else if (remaining_children_to_start) { |
| 3188 | /* we're still doing a 1-for-1 replacement of dead |
no test coverage detected