| 2904 | } |
| 2905 | |
| 2906 | static void perform_idle_server_maintenance(int child_bucket, |
| 2907 | int *max_daemon_used) |
| 2908 | { |
| 2909 | int num_buckets = retained->mpm->num_buckets; |
| 2910 | int idle_thread_count = 0; |
| 2911 | process_score *ps; |
| 2912 | int free_length = 0; |
| 2913 | int free_slots[MAX_SPAWN_RATE]; |
| 2914 | int last_non_dead = -1; |
| 2915 | int active_thread_count = 0; |
| 2916 | int i, j; |
| 2917 | |
| 2918 | for (i = 0; i < server_limit; ++i) { |
| 2919 | if (num_buckets > 1 && (i % num_buckets) != child_bucket) { |
| 2920 | /* We only care about child_bucket in this call */ |
| 2921 | continue; |
| 2922 | } |
| 2923 | if (i >= retained->max_daemon_used && |
| 2924 | free_length == retained->idle_spawn_rate[child_bucket]) { |
| 2925 | /* short cut if all active processes have been examined and |
| 2926 | * enough empty scoreboard slots have been found |
| 2927 | */ |
| 2928 | break; |
| 2929 | } |
| 2930 | |
| 2931 | ps = &ap_scoreboard_image->parent[i]; |
| 2932 | if (ps->pid != 0) { |
| 2933 | int child_threads_active = 0; |
| 2934 | if (ps->quiescing == 1) { |
| 2935 | ps->quiescing = 2; |
| 2936 | retained->active_daemons--; |
| 2937 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, |
| 2938 | "Child %d quiescing: pid %d, gen %d, " |
| 2939 | "active %d/%d, total %d/%d/%d", |
| 2940 | i, (int)ps->pid, (int)ps->generation, |
| 2941 | retained->active_daemons, active_daemons_limit, |
| 2942 | retained->total_daemons, retained->max_daemon_used, |
| 2943 | server_limit); |
| 2944 | } |
| 2945 | for (j = 0; j < threads_per_child; j++) { |
| 2946 | int status = ap_scoreboard_image->servers[i][j].status; |
| 2947 | |
| 2948 | /* We consider a starting server as idle because we started it |
| 2949 | * at least a cycle ago, and if it still hasn't finished starting |
| 2950 | * then we're just going to swamp things worse by forking more. |
| 2951 | * So we hopefully won't need to fork more if we count it. |
| 2952 | * This depends on the ordering of SERVER_READY and SERVER_STARTING. |
| 2953 | */ |
| 2954 | if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting |
| 2955 | && ps->generation == retained->mpm->my_generation) { |
| 2956 | ++idle_thread_count; |
| 2957 | } |
| 2958 | if (status >= SERVER_READY && status < SERVER_GRACEFUL) { |
| 2959 | ++child_threads_active; |
| 2960 | } |
| 2961 | } |
| 2962 | active_thread_count += child_threads_active; |
| 2963 | if (child_threads_active == threads_per_child) { |
no test coverage detected