XXX For ungraceful termination/restart, we definitely don't want to * wait for active connections to finish but we may want to wait * for idle workers to get out of the queue code and release mutexes, * since those mutexes are cleaned up pretty soon and some systems * may not react favorably (i.e., segfault) if operations are attempted * on cleaned-up mutexes. */
| 740 | * on cleaned-up mutexes. |
| 741 | */ |
| 742 | static void * APR_THREAD_FUNC worker_thread(apr_thread_t *thd, void * dummy) |
| 743 | { |
| 744 | proc_info * ti = dummy; |
| 745 | int process_slot = ti->pid; |
| 746 | int thread_slot = ti->tid; |
| 747 | apr_socket_t *csd = NULL; |
| 748 | apr_bucket_alloc_t *bucket_alloc; |
| 749 | apr_pool_t *last_ptrans = NULL; |
| 750 | apr_pool_t *ptrans; /* Pool for per-transaction stuff */ |
| 751 | apr_status_t rv; |
| 752 | int is_idle = 0; |
| 753 | |
| 754 | free(ti); |
| 755 | |
| 756 | ap_scoreboard_image->servers[process_slot][thread_slot].pid = ap_my_pid; |
| 757 | ap_scoreboard_image->servers[process_slot][thread_slot].tid = apr_os_thread_current(); |
| 758 | ap_scoreboard_image->servers[process_slot][thread_slot].generation = retained->mpm->my_generation; |
| 759 | ap_update_child_status_from_indexes(process_slot, thread_slot, |
| 760 | SERVER_STARTING, NULL); |
| 761 | |
| 762 | #ifdef HAVE_PTHREAD_KILL |
| 763 | apr_signal(WORKER_SIGNAL, dummy_signal_handler); |
| 764 | unblock_signal(WORKER_SIGNAL); |
| 765 | #endif |
| 766 | |
| 767 | while (!workers_may_exit) { |
| 768 | if (!is_idle) { |
| 769 | rv = ap_queue_info_set_idle(worker_queue_info, last_ptrans); |
| 770 | last_ptrans = NULL; |
| 771 | if (rv != APR_SUCCESS) { |
| 772 | ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, |
| 773 | "ap_queue_info_set_idle failed. Attempting to " |
| 774 | "shutdown process gracefully."); |
| 775 | signal_threads(ST_GRACEFUL); |
| 776 | break; |
| 777 | } |
| 778 | is_idle = 1; |
| 779 | } |
| 780 | |
| 781 | ap_update_child_status_from_indexes(process_slot, thread_slot, |
| 782 | SERVER_READY, NULL); |
| 783 | worker_pop: |
| 784 | if (workers_may_exit) { |
| 785 | break; |
| 786 | } |
| 787 | rv = ap_queue_pop_socket(worker_queue, &csd, &ptrans); |
| 788 | |
| 789 | if (rv != APR_SUCCESS) { |
| 790 | /* We get APR_EOF during a graceful shutdown once all the connections |
| 791 | * accepted by this server process have been handled. |
| 792 | */ |
| 793 | if (APR_STATUS_IS_EOF(rv)) { |
| 794 | break; |
| 795 | } |
| 796 | /* We get APR_EINTR whenever ap_queue_pop_*() has been interrupted |
| 797 | * from an explicit call to ap_queue_interrupt_all(). This allows |
| 798 | * us to unblock threads stuck in ap_queue_pop_*() when a shutdown |
| 799 | * is pending. |
nothing calls this directly
no test coverage detected