# HG changeset patch # User Igor Sysoev # Date 1199813439 0 # Node ID 056347360e141f140eff5199a2fea60b6d61ae2d # Parent 40116ff1cbd47d145c1e34199b8ec381641755d2 r1755, r1756, r1757 merge: *) SSL_shutdown() never returns -1, on error it returns 0. This fixes incidental "bad write retry" errors. *) cleaning stale global SSL error *) remove SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER, we never need it diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -22,6 +22,7 @@ static void ngx_ssl_read_handler(ngx_eve static void ngx_ssl_shutdown_handler(ngx_event_t *ev); static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, ngx_err_t err, char *text); +static void ngx_ssl_clear_error(ngx_log_t *log); static ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); @@ -186,8 +187,6 @@ ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_ SSL_CTX_set_options(ssl->ctx, ngx_ssl_protocols[protocols >> 1]); } - SSL_CTX_set_mode(ssl->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - SSL_CTX_set_read_ahead(ssl->ctx, 1); return NGX_OK; @@ -404,6 +403,8 @@ ngx_ssl_handshake(ngx_connection_t *c) int n, sslerr; ngx_err_t err; + ngx_ssl_clear_error(c->log); + n = SSL_do_handshake(c->ssl->connection); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_do_handshake: %d", n); @@ -602,6 +603,8 @@ ngx_ssl_recv(ngx_connection_t *c, u_char bytes = 0; + ngx_ssl_clear_error(c->log); + /* * SSL_read() may return data in parts, so try to read * until SSL_read() would return no data @@ -882,6 +885,8 @@ ngx_ssl_write(ngx_connection_t *c, u_cha int n, sslerr; ngx_err_t err; + ngx_ssl_clear_error(c->log); + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL to write: %d", size); n = SSL_write(c->ssl->connection, data, size); @@ -965,9 +970,8 @@ ngx_ssl_read_handler(ngx_event_t *rev) ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c) { - int n, sslerr, mode; - ngx_err_t err; - ngx_uint_t again; + int n, sslerr, mode; + ngx_err_t err; if (c->timedout) { mode = SSL_RECEIVED_SHUTDOWN|SSL_SENT_SHUTDOWN; @@ -986,40 +990,34 @@ ngx_ssl_shutdown(ngx_connection_t *c) SSL_set_shutdown(c->ssl->connection, mode); - again = 0; + ngx_ssl_clear_error(c->log); + + n = SSL_shutdown(c->ssl->connection); + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n); + sslerr = 0; - for ( ;; ) { - n = SSL_shutdown(c->ssl->connection); - - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_shutdown: %d", n); - - if (n == 1 || (n == 0 && c->timedout)) { - SSL_free(c->ssl->connection); - c->ssl = NULL; - - return NGX_OK; - } - - if (n == 0) { - again = 1; - break; - } - - break; - } - - if (!again) { + /* SSL_shutdown() never return -1, on error it return 0 */ + + if (n != 1) { sslerr = SSL_get_error(c->ssl->connection, n); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_get_error: %d", sslerr); } - if (again - || sslerr == SSL_ERROR_WANT_READ - || sslerr == SSL_ERROR_WANT_WRITE) + if (n == 1 + || sslerr == SSL_ERROR_ZERO_RETURN + || (sslerr == 0 && c->timedout)) { + SSL_free(c->ssl->connection); + c->ssl = NULL; + + return NGX_OK; + } + + if (sslerr == SSL_ERROR_WANT_READ || sslerr == SSL_ERROR_WANT_WRITE) { c->read->handler = ngx_ssl_shutdown_handler; c->write->handler = ngx_ssl_shutdown_handler; @@ -1031,7 +1029,7 @@ ngx_ssl_shutdown(ngx_connection_t *c) return NGX_ERROR; } - if (again || sslerr == SSL_ERROR_WANT_READ) { + if (sslerr == SSL_ERROR_WANT_READ) { ngx_add_timer(c->read, 30000); } @@ -1112,6 +1110,15 @@ ngx_ssl_connection_error(ngx_connection_ } +static void +ngx_ssl_clear_error(ngx_log_t *log) +{ + if (ERR_peek_error()) { + ngx_ssl_error(NGX_LOG_ALERT, log, 0, "ignoring stale global SSL error"); + } +} + + void ngx_cdecl ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) {