diff options
author | Yann Ylavic <ylavic@apache.org> | 2017-10-10 12:54:48 +0200 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2017-10-10 12:54:48 +0200 |
commit | 0583afb6ea5b30b82da08168cd7e8d3bc1cfebbd (patch) | |
tree | b6f3e8a54fbd4f4542cda1cfa6e3fe8c97f6b2e0 /support | |
parent | ab: Keep reading nonblocking to exhaust TCP or SSL buffers when previous (diff) | |
download | apache2-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.c | 67 |
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); + } } } } |