summaryrefslogtreecommitdiffstats
path: root/support
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2023-07-07 17:52:45 +0200
committerYann Ylavic <ylavic@apache.org>2023-07-07 17:52:45 +0200
commita9b1f101563f42b7c4a9787f0d56dc13239d8c3e (patch)
tree0dbaa9fc534b9ee882c20afee21188f38065af61 /support
parentAdd WebAssembly MIME type and file extension (diff)
downloadapache2-a9b1f101563f42b7c4a9787f0d56dc13239d8c3e.tar.xz
apache2-a9b1f101563f42b7c4a9787f0d56dc13239d8c3e.zip
ab: Fix accounting of started connections.
Revert when a kept alive connection is aborted on read. Stop the polling loop when there is nothing to poll anymore, it's simpler. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1910861 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'support')
-rw-r--r--support/ab.c64
1 files changed, 39 insertions, 25 deletions
diff --git a/support/ab.c b/support/ab.c
index f21fb8ea97..a0b0c5ac3e 100644
--- a/support/ab.c
+++ b/support/ab.c
@@ -176,6 +176,7 @@
#if APR_HAVE_LIMITS_H
#include <limits.h>
#endif
+#include <assert.h>
#if defined(HAVE_OPENSSL)
@@ -357,6 +358,7 @@ struct worker {
int slot;
int requests;
int concurrency;
+ int polled;
int succeeded_once; /* response header received once */
apr_int64_t started; /* number of requests started, so no excess */
@@ -477,14 +479,14 @@ static apr_thread_mutex_t *workers_mutex;
static apr_thread_cond_t *workers_can_start;
#endif
-static APR_INLINE int worker_should_stop(struct worker *worker)
+static APR_INLINE int worker_can_stop(struct worker *worker)
{
return (lasttime >= stoptime
|| (rlimited && worker->metrics.done >= worker->requests));
}
-static APR_INLINE int worker_can_start_connection(struct worker *worker)
+static APR_INLINE int worker_can_connect(struct worker *worker)
{
- return !(worker_should_stop(worker)
+ return !(lasttime >= stoptime
|| (rlimited && worker->started >= worker->requests));
}
@@ -617,7 +619,9 @@ static int set_polled_events(struct connection *c, apr_int16_t new_reqevents)
graceful_strerror("apr_pollset_remove()", rv);
return 0;
}
- }
+ assert(c->worker->polled > 0);
+ c->worker->polled--;
+ }
c->pollfd.reqevents = new_reqevents;
if (new_reqevents != 0) {
@@ -626,6 +630,7 @@ static int set_polled_events(struct connection *c, apr_int16_t new_reqevents)
graceful_strerror("apr_pollset_add()", rv);
return 0;
}
+ c->worker->polled++;
}
}
return 1;
@@ -809,7 +814,7 @@ static void ssl_print_info(struct connection *c)
for (i=1; i<count; i++) {
cert = (X509 *)SK_VALUE(sk, i);
ssl_print_cert_info(bio_out, cert);
- }
+ }
}
cert = SSL_get_peer_certificate(c->ssl);
if (cert == NULL) {
@@ -1581,7 +1586,7 @@ static void start_connection(struct connection * c)
struct worker *worker = c->worker;
apr_status_t rv;
- if (!worker_can_start_connection(worker)) {
+ if (!worker_can_connect(worker)) {
return;
}
@@ -1758,6 +1763,7 @@ static void finalize_connection(struct connection *c, int reuse)
{
struct worker *worker = c->worker;
int good = (c->gotheader && c->bread >= c->length);
+ int final_state = c->state;
/* close before measuring, to account for shutdown time */
if (!reuse || !good) {
@@ -1772,12 +1778,15 @@ static void finalize_connection(struct connection *c, int reuse)
*/
worker->metrics.doneka--;
worker->metrics.aborted_ka++;
+ if (final_state > STATE_WRITE) {
+ worker->started--;
+ }
}
else {
/* save out time */
if (tlimit || worker->metrics.done < worker->requests) {
apr_time_t tnow = lasttime = c->end = apr_time_now();
- struct data *s = &worker->stats[worker->metrics.done++ % worker->requests];
+ struct data *s = &worker->stats[worker->metrics.done % worker->requests];
/* Cumulative for when worker->metrics.done > worker->requests (tlimit),
* consolidate_metrics() will do the mean.
@@ -1839,6 +1848,7 @@ static void finalize_connection(struct connection *c, int reuse)
}
}
}
+ worker->metrics.done++;
/* update worker's metrics */
if (good) {
@@ -1858,9 +1868,9 @@ static void finalize_connection(struct connection *c, int reuse)
}
if (!reuse) {
- start_connection(c); /* nop if !worker_can_start_connection() */
+ start_connection(c); /* nop if !worker_can_connect() */
}
- else if (worker_can_start_connection(worker)) {
+ else if (worker_can_connect(worker)) {
c->keptalive++;
worker->metrics.doneka++;
@@ -2435,20 +2445,22 @@ static void worker_test(struct worker *worker)
apr_int32_t n;
const apr_pollfd_t *pollresults, *pollfd;
apr_interval_time_t t = aprtimeout;
- apr_time_t now = apr_time_now();
-
- while (!APR_RING_EMPTY(&worker->delayed_ring, connection, delay_list)) {
- c = APR_RING_FIRST(&worker->delayed_ring);
- if (c->delay <= now) {
- APR_RING_REMOVE(c, delay_list);
- APR_RING_ELEM_INIT(c, delay_list);
- c->delay = 0;
- start_connection(c);
- }
- else {
- t = c->delay - now;
- break;
- }
+
+ if (!APR_RING_EMPTY(&worker->delayed_ring, connection, delay_list)) {
+ apr_time_t now = apr_time_now();
+ do {
+ c = APR_RING_FIRST(&worker->delayed_ring);
+ if (c->delay <= now) {
+ APR_RING_REMOVE(c, delay_list);
+ APR_RING_ELEM_INIT(c, delay_list);
+ c->delay = 0;
+ start_connection(c);
+ }
+ else {
+ t = c->delay - now;
+ break;
+ }
+ } while (!APR_RING_EMPTY(&worker->delayed_ring, connection, delay_list));
}
n = worker->metrics.concurrent;
@@ -2561,7 +2573,9 @@ static void worker_test(struct worker *worker)
continue;
}
}
- } while (!worker_should_stop(worker));
+ } while (worker->polled > 0 && stoptime);
+
+ assert(worker_can_stop(worker));
}
#if APR_HAS_THREADS
@@ -3312,7 +3326,7 @@ int main(int argc, const char * const argv[])
exit(1);
}
#endif
-
+
if (!(ssl_ctx = SSL_CTX_new(meth))) {
BIO_printf(bio_err, "Could not initialize SSL Context.\n");
ERR_print_errors(bio_err);