Browse Source

[streams] improve stream handling, hopefully fixes bug with lingering backend connections

- reset backend_source before backend_drain; first tell the backend we
  are not interested in data anymore, then force closing the outgoing
  data
- as backend_drain might get reopened for a Connection: upgrade, the
  backend cannot rely on backend_drain->out.is_closed, but waits for a
  disconnect (which will also release the last reference).  the same is
  done for backend_source, so a backend can just wait for both reference
  counts to drop to zero before actually closing the backend connection
  (unless it keeps the streams alive itself).

Change-Id: Ibfe7985debd71580dbb78b985abaf946f59e3024
master
Stefan Bühler 5 years ago
parent
commit
535f6b4afb
2 changed files with 11 additions and 17 deletions
  1. +7
    -1
      src/main/stream_http_response.c
  2. +4
    -16
      src/main/virtualrequest.c

+ 7
- 1
src/main/stream_http_response.c View File

@@ -80,7 +80,13 @@ static void check_response_header(liStreamHttpResponse* shr) {
}
shr->response_headers_finished = TRUE;
shr->vr->backend_drain->out->is_closed = FALSE;
li_vrequest_connection_upgrade(shr->vr, shr->vr->backend_drain, &shr->stream);
{
/* li_vrequest_connection_upgrade releases vr->backend_drain; keep our own reference */
liStream *backend_drain = shr->vr->backend_drain;
shr->vr->backend_drain = NULL;
li_vrequest_connection_upgrade(shr->vr, backend_drain, &shr->stream);
li_stream_release(backend_drain);
}
return;
}



+ 4
- 16
src/main/virtualrequest.c View File

@@ -53,9 +53,9 @@ liVRequest* li_vrequest_new(liWorker *wrk, liConInfo *coninfo) {
void li_vrequest_free(liVRequest* vr) {
liServer *srv = vr->wrk->srv;

li_stream_safe_reset_and_release(&vr->backend_drain);
vr->direct_out = NULL;
li_stream_safe_reset_and_release(&vr->backend_source);
li_stream_safe_reset_and_release(&vr->backend_drain);

li_filter_buffer_on_disk_stop(vr->in_buffer_on_disk_stream);
li_stream_safe_reset_and_release(&vr->in_buffer_on_disk_stream);
@@ -102,21 +102,9 @@ void li_vrequest_free(liVRequest* vr) {
void li_vrequest_reset(liVRequest *vr, gboolean keepalive) {
liServer *srv = vr->wrk->srv;

if (NULL != vr->backend_drain) {
li_stream_disconnect(vr->backend_drain);
li_stream_release(vr->backend_drain);
vr->backend_drain = NULL;
}
if (NULL != vr->backend_source) {
if (NULL == vr->backend_source->dest) {
/* wasn't connected: disconnect source */
li_stream_disconnect(vr->backend_source);
}
li_stream_disconnect_dest(vr->backend_source);
li_stream_release(vr->backend_source);
vr->backend_source = NULL;
vr->direct_out = NULL;
}
vr->direct_out = NULL;
li_stream_safe_reset_and_release(&vr->backend_source);
li_stream_safe_reset_and_release(&vr->backend_drain);

li_filter_buffer_on_disk_stop(vr->in_buffer_on_disk_stream);
li_stream_safe_reset_and_release(&vr->in_buffer_on_disk_stream);


Loading…
Cancel
Save