summaryrefslogtreecommitdiffstats
path: root/support
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2017-10-10 12:54:48 +0200
committerYann Ylavic <ylavic@apache.org>2017-10-10 12:54:48 +0200
commit0583afb6ea5b30b82da08168cd7e8d3bc1cfebbd (patch)
treeb6f3e8a54fbd4f4542cda1cfa6e3fe8c97f6b2e0 /support
parentab: Keep reading nonblocking to exhaust TCP or SSL buffers when previous (diff)
downloadapache2-0583afb6ea5b30b82da08168cd7e8d3bc1cfebbd.tar.xz
apache2-0583afb6ea5b30b82da08168cd7e8d3bc1cfebbd.zip
ab: Make the TLS layer aware that the underlying socket is nonblocking,
and use/handle POLLOUT where needed to avoid busy IOs and recover write errors when appropriate. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1811664 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'support')
-rw-r--r--support/ab.c67
1 files changed, 49 insertions, 18 deletions
diff --git a/support/ab.c b/support/ab.c
index d8486ea769..89310a0df8 100644
--- a/support/ab.c
+++ b/support/ab.c
@@ -776,8 +776,8 @@ static void ssl_proceed_handshake(struct connection *c)
do_next = 0;
break;
case SSL_ERROR_WANT_WRITE:
- /* Try again */
- do_next = 1;
+ set_polled_events(c, APR_POLLOUT);
+ do_next = 0;
break;
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_SSL:
@@ -827,26 +827,42 @@ static void write_request(struct connection * c)
#ifdef USE_SSL
if (c->ssl) {
- apr_size_t e_ssl;
- e_ssl = SSL_write(c->ssl,request + c->rwrote, l);
- if (e_ssl != l) {
- BIO_printf(bio_err, "SSL write failed - closing connection\n");
- ERR_print_errors(bio_err);
- close_connection (c);
+ e = SSL_write(c->ssl, request + c->rwrote, l);
+ if (e <= 0) {
+ switch (SSL_get_error(c->ssl, e)) {
+ case SSL_ERROR_WANT_READ:
+ set_polled_events(c, APR_POLLIN);
+ break;
+ case SSL_ERROR_WANT_WRITE:
+ set_polled_events(c, APR_POLLOUT);
+ break;
+ default:
+ BIO_printf(bio_err, "SSL write failed - closing connection\n");
+ ERR_print_errors(bio_err);
+ close_connection (c);
+ break;
+ }
return;
}
- l = e_ssl;
+ l = e;
e = APR_SUCCESS;
}
else
#endif
+ {
e = apr_socket_send(c->aprsock, request + c->rwrote, &l);
-
- if (e != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(e)) {
- epipe++;
- printf("Send request failed!\n");
- close_connection(c);
- return;
+ if (e != APR_SUCCESS) {
+ if (!APR_STATUS_IS_EAGAIN(e)) {
+ epipe++;
+ printf("Send request failed!\n");
+ close_connection(c);
+ return;
+ }
+ if (!l) {
+ set_polled_events(c, APR_POLLOUT);
+ return;
+ }
+ }
}
totalposted += l;
c->rwrote += l;
@@ -1387,6 +1403,7 @@ static void start_connect(struct connection * c)
ssl_rand_seed();
apr_os_sock_get(&fd, c->aprsock);
bio = BIO_new_socket(fd, BIO_NOCLOSE);
+ BIO_set_nbio(bio, 1);
SSL_set_bio(c->ssl, bio, bio);
SSL_set_connect_state(c->ssl);
if (verbosity >= 4) {
@@ -1535,8 +1552,13 @@ read_more:
&& good == 0) {
return;
}
- else if (scode != SSL_ERROR_WANT_WRITE
- && scode != SSL_ERROR_WANT_READ) {
+ else if (scode == SSL_ERROR_WANT_READ) {
+ set_polled_events(c, APR_POLLIN);
+ }
+ else if (scode == SSL_ERROR_WANT_WRITE) {
+ set_polled_events(c, APR_POLLOUT);
+ }
+ else {
/* some fatal error: */
c->read = 0;
BIO_printf(bio_err, "SSL read failed (%d) - closing connection\n", scode);
@@ -1750,6 +1772,7 @@ read_more:
c->read = c->bread = 0;
/* zero connect time with keep-alive */
c->start = c->connect = lasttime = apr_time_now();
+ set_conn_state(c, STATE_CONNECTED);
write_request(c);
}
}
@@ -1996,6 +2019,7 @@ static void test(void)
}
if (rtnev & APR_POLLOUT) {
if (c->state == STATE_CONNECTING) {
+ /* call connect() again to detect errors */
rv = apr_socket_connect(c->aprsock, destsa);
if (rv != APR_SUCCESS) {
set_conn_state(c, STATE_UNCONNECTED);
@@ -2020,7 +2044,14 @@ static void test(void)
}
}
else {
- write_request(c);
+ /* POLLOUT is one shot */
+ set_polled_events(c, APR_POLLIN);
+ if (c->state == STATE_READ) {
+ read_connection(c);
+ }
+ else {
+ write_request(c);
+ }
}
}
}