Hi Luca, [better/easier to talk about details on dev@]
On Fri, Jun 30, 2017 at 11:05 AM, <bugzi...@apache.org> wrote: > https://bz.apache.org/bugzilla/show_bug.cgi?id=60956 > > --- Comment #11 from Luca Toscano <toscano.l...@gmail.com> --- > Other two interesting trunk improvements that have not been backported yet: > > http://svn.apache.org/viewvc?view=revision&revision=1706669 > http://svn.apache.org/viewvc?view=revision&revision=1734656 > > IIUC these ones are meant to provide a more async behavior to most of the > output filters, namely setting aside buckets (on the heap) to avoid blocking. These are quite orthogonal I think, and don't seem to fix this particular issue. > > After a bit of thinking it seems to me that we'd need to find a solution that > prevents the mod_ssl_output filter to block, but in a safe way. IMHO mod_ssl shoudn't (BIO_)flush unconditionally in modssl_smart_shutdown(), only in the "abortive" mode of ssl_filter_io_shutdown(). The caller of the ssl output filters should decide when to flush, so http://svn.apache.org/r1651077 was not the good fix in this regard. Even if we don't BIO_flush, openssl shouldn't retain the close-notify by itself, so at least it should go down to the next/core ouput filter (and stay there until the socket is write-able or asked to flush). > > In this particular case we assume this about > start_lingering_close_nonblocking: > > """ > /* > * Close our side of the connection, NOT flushing data to the client. > * This should only be called if there has been an error or if we know > * that our send buffers are empty. > * Pre-condition: cs is not in any timeout queue and not in the pollset, > * timeout_mutex is not locked > * return: 0 if connection is fully closed, > * 1 if connection is lingering > * may be called by listener thread > */ > """ > > I tried the following patch: > > """ > Index: server/mpm/event/event.c > =================================================================== > --- server/mpm/event/event.c (revision 1800362) > +++ server/mpm/event/event.c (working copy) > @@ -744,10 +744,7 @@ > conn_rec *c = cs->c; > apr_socket_t *csd = cs->pfd.desc.s; > > - if (ap_prep_lingering_close(c) > - || c->aborted > - || ap_shutdown_conn(c, 0) != APR_SUCCESS || c->aborted > - || apr_socket_shutdown(csd, APR_SHUTDOWN_WRITE) != APR_SUCCESS) { > + if (ap_prep_lingering_close(c) || c->aborted) { > apr_socket_close(csd); > ap_push_pool(worker_queue_info, cs->p); > if (dying) > """ > > So the idea was to brutally close the connection only if > ap_prep_lingering_close(c) is not 0 or if the client has already aborted, but > to leave all the other cases to the start_lingering_close_common. This is > probably not enough/correct because the connection would go into the > lingering_close queue, to be picked up again by > process_timeout_queue(linger_q,..) after the timeout that would call > stop_lingering_close, that would in turn simply close the socket without > giving > the possibility to mod_ssl to flush its close-notify (because no > ap_shutdown_conn would be called). With a possibly non-blocking modssl_smart_shutdown(), I think we could make ap_shutdown_conn(c, 0) return something like APR_INCOMPLETE for the case the shutdown was "buffered" in the output filter stack (e.g. core output filter). In mpm_event, we would then go to (or stay in) the WRITE_COMPLETION state instead of LINGER, until every remaining piece data is flushed successfully. Does this sound OK?