From 6ff23b5f8018136b7a707473d5eb1037470d4987 Mon Sep 17 00:00:00 2001 From: Greg Stein Date: Sun, 16 Nov 2003 23:03:18 +0000 Subject: [PATCH] Switch the prefork MPM over to the new pollset interface. * server/mpm/prefork/prefork.c: (listensocks[]): removed. not required. (child_main): stop using listensocks[] in favor of an apr_pollset_t. if there is just one listener, then always refer to that listener's listen_rec for further processing, otherwise poll and pick up the listen_rec pointer from the polling structure's client_data. tweaked the round-robin for the new pollset API (and documented). cleaning: removed 'offset' which is obviated by the use of a pointer to a listen_rec. tighten the block-scope of several variables. switch to use a 'status' variable name rather than three separately named variables. rename n->numdesc to be more obvious. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@101799 13f79535-47bb-0310-9956-ffa450edef68 --- server/mpm/prefork/prefork.c | 107 ++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 51 deletions(-) diff --git a/server/mpm/prefork/prefork.c b/server/mpm/prefork/prefork.c index 3867c0ee93..c06b258dd4 100644 --- a/server/mpm/prefork/prefork.c +++ b/server/mpm/prefork/prefork.c @@ -476,7 +476,7 @@ static void set_signals(void) static int requests_this_child; static int num_listensocks = 0; -static ap_listen_rec *listensocks; + int ap_graceful_stop_signalled(void) { @@ -489,21 +489,16 @@ static void child_main(int child_num_arg) { apr_pool_t *ptrans; apr_allocator_t *allocator; - conn_rec *current_conn; - apr_status_t status = APR_EINIT; + apr_status_t status; int i; ap_listen_rec *lr; - int curr_pollfd, last_pollfd = 0; - apr_pollfd_t *pollset; - int offset; - void *csd; + apr_pollset_t *pollset; ap_sb_handle_t *sbh; - apr_status_t rv; apr_bucket_alloc_t *bucket_alloc; + int last_poll_idx = 0; my_child_num = child_num_arg; ap_my_pid = getpid(); - csd = NULL; requests_this_child = 0; ap_fatal_signal_child_setup(ap_server_conf); @@ -521,9 +516,9 @@ static void child_main(int child_num_arg) /* needs to be done before we switch UIDs so we have permissions */ ap_reopen_scoreboard(pchild, NULL, 0); - rv = apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild); - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_EMERG, rv, ap_server_conf, + status = apr_proc_mutex_child_init(&accept_mutex, ap_lock_fname, pchild); + if (status != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_EMERG, status, ap_server_conf, "Couldn't initialize cross-process lock in child"); clean_child_exit(APEXIT_CHILDFATAL); } @@ -539,30 +534,31 @@ static void child_main(int child_num_arg) (void) ap_update_child_status(sbh, SERVER_READY, (request_rec *) NULL); /* Set up the pollfd array */ - listensocks = apr_pcalloc(pchild, - sizeof(*listensocks) * (num_listensocks)); - for (lr = ap_listeners, i = 0; i < num_listensocks; lr = lr->next, i++) { - listensocks[i].accept_func = lr->accept_func; - listensocks[i].sd = lr->sd; - } + /* ### check the status */ + (void) apr_pollset_create(&pollset, num_listensocks, pchild, 0); + + for (lr = ap_listeners, i = num_listensocks; i--; lr = lr->next) { + apr_pollfd_t pfd = { 0 }; + + pfd.desc_type = APR_POLL_SOCKET; + pfd.desc.s = lr->sd; + pfd.reqevents = APR_POLLIN; + pfd.client_data = lr; - pollset = apr_palloc(pchild, sizeof(*pollset) * num_listensocks); - pollset[0].p = pchild; - for (i = 0; i < num_listensocks; i++) { - pollset[i].desc.s = listensocks[i].sd; - pollset[i].desc_type = APR_POLL_SOCKET; - pollset[i].reqevents = APR_POLLIN; + /* ### check the status */ + (void) apr_pollset_add(pollset, &pfd); } bucket_alloc = apr_bucket_alloc_create(pchild); while (!die_now) { + conn_rec *current_conn; + void *csd; + /* * (Re)initialize this child to a pre-connection state. */ - current_conn = NULL; - apr_pool_clear(ptrans); if ((ap_max_requests_per_child > 0 @@ -580,17 +576,19 @@ static void child_main(int child_num_arg) SAFE_ACCEPT(accept_mutex_on()); if (num_listensocks == 1) { - offset = 0; + /* There is only one listener record, so refer to that one. */ + lr = ap_listeners; } else { /* multiple listening sockets - need to poll */ for (;;) { - apr_status_t ret; - apr_int32_t n; + apr_int32_t numdesc; + const apr_pollfd_t *pdesc; - ret = apr_poll(pollset, num_listensocks, &n, -1); - if (ret != APR_SUCCESS) { - if (APR_STATUS_IS_EINTR(ret)) { + /* timeout == -1 == wait forever */ + status = apr_pollset_poll(pollset, -1, &numdesc, &pdesc); + if (status != APR_SUCCESS) { + if (APR_STATUS_IS_EINTR(status)) { if (one_process && shutdown_pending) { return; } @@ -602,34 +600,41 @@ static void child_main(int child_num_arg) * on Linux 2.0.x we seem to end up with EFAULT * occasionally, and we'd loop forever due to it. */ - ap_log_error(APLOG_MARK, APLOG_ERR, ret, ap_server_conf, - "apr_poll: (listen)"); + ap_log_error(APLOG_MARK, APLOG_ERR, status, + ap_server_conf, "apr_poll: (listen)"); clean_child_exit(1); } - /* find a listener */ - curr_pollfd = last_pollfd; - do { - curr_pollfd++; - if (curr_pollfd >= num_listensocks) { - curr_pollfd = 0; - } - /* XXX: Should we check for POLLERR? */ - if (pollset[curr_pollfd].rtnevents & APR_POLLIN) { - last_pollfd = curr_pollfd; - offset = curr_pollfd; - goto got_fd; - } - } while (curr_pollfd != last_pollfd); - continue; + /* We can always use pdesc[0], but sockets at position N + * could end up completely starved of attention in a very + * busy server. Therefore, we round-robin across the + * returned set of descriptors. While it is possible that + * the returned set of descriptors might flip around and + * continue to starve some sockets, we happen to know the + * internal pollset implementation retains ordering + * stability of the sockets. Thus, the round-robin should + * ensure that a socket will eventually be serviced. + */ + if (last_poll_idx >= numdesc) + last_poll_idx = 0; + + /* Grab a listener record from the client_data of the poll + * descriptor, and advance our saved index to round-robin + * the next fetch. + * + * ### hmm... this descriptor might have POLLERR rather + * ### than POLLIN + */ + lr = pdesc[last_poll_idx++].client_data; + goto got_fd; } } got_fd: /* if we accept() something we don't want to die, so we have to * defer the exit */ - status = listensocks[offset].accept_func(&csd, - &listensocks[offset], ptrans); + status = lr->accept_func(&csd, lr, ptrans); + SAFE_ACCEPT(accept_mutex_off()); /* unlock after "accept" */ if (status == APR_EGENERAL) { -- 2.40.0