| 796 | } |
| 797 | |
| 798 | static void perform_idle_server_maintenance(apr_pool_t *p) |
| 799 | { |
| 800 | int i; |
| 801 | int idle_count; |
| 802 | worker_score *ws; |
| 803 | int free_length; |
| 804 | int free_slots[MAX_SPAWN_RATE]; |
| 805 | int last_non_dead; |
| 806 | int total_non_dead; |
| 807 | |
| 808 | /* initialize the free_list */ |
| 809 | free_length = 0; |
| 810 | |
| 811 | idle_count = 0; |
| 812 | last_non_dead = -1; |
| 813 | total_non_dead = 0; |
| 814 | |
| 815 | for (i = 0; i < ap_daemons_limit; ++i) { |
| 816 | int status; |
| 817 | |
| 818 | if (i >= retained->max_daemons_limit && free_length == retained->idle_spawn_rate) |
| 819 | break; |
| 820 | ws = &ap_scoreboard_image->servers[i][0]; |
| 821 | status = ws->status; |
| 822 | if (status == SERVER_DEAD) { |
| 823 | /* try to keep children numbers as low as possible */ |
| 824 | if (free_length < retained->idle_spawn_rate) { |
| 825 | free_slots[free_length] = i; |
| 826 | ++free_length; |
| 827 | } |
| 828 | } |
| 829 | else { |
| 830 | /* We consider a starting server as idle because we started it |
| 831 | * at least a cycle ago, and if it still hasn't finished starting |
| 832 | * then we're just going to swamp things worse by forking more. |
| 833 | * So we hopefully won't need to fork more if we count it. |
| 834 | * This depends on the ordering of SERVER_READY and SERVER_STARTING. |
| 835 | */ |
| 836 | if (status <= SERVER_READY) { |
| 837 | ++ idle_count; |
| 838 | } |
| 839 | |
| 840 | ++total_non_dead; |
| 841 | last_non_dead = i; |
| 842 | } |
| 843 | } |
| 844 | retained->max_daemons_limit = last_non_dead + 1; |
| 845 | if (idle_count > ap_daemons_max_free) { |
| 846 | static int bucket_kill_child_record = -1; |
| 847 | /* kill off one child... we use the pod because that'll cause it to |
| 848 | * shut down gracefully, in case it happened to pick up a request |
| 849 | * while we were counting |
| 850 | */ |
| 851 | bucket_kill_child_record = (bucket_kill_child_record + 1) % retained->mpm->num_buckets; |
| 852 | ap_mpm_pod_signal(all_buckets[bucket_kill_child_record].pod); |
| 853 | retained->idle_spawn_rate = 1; |
| 854 | } |
| 855 | else if (idle_count < ap_daemons_min_free) { |
no test coverage detected