diff options
Diffstat (limited to 'src/stream.c')
-rw-r--r-- | src/stream.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/src/stream.c b/src/stream.c index a3c0c93..e643a6d 100644 --- a/src/stream.c +++ b/src/stream.c @@ -537,7 +537,7 @@ struct stream *stream_new(struct session *sess, struct stconn *sc, struct buffer s->res.analyse_exp = TICK_ETERNITY; s->txn = NULL; - s->hlua = NULL; + s->hlua[0] = s->hlua[1] = NULL; s->resolv_ctx.requester = NULL; s->resolv_ctx.hostname_dn = NULL; @@ -649,8 +649,10 @@ void stream_free(struct stream *s) flt_stream_stop(s); flt_stream_release(s, 0); - hlua_ctx_destroy(s->hlua); - s->hlua = NULL; + hlua_ctx_destroy(s->hlua[0]); + hlua_ctx_destroy(s->hlua[1]); + s->hlua[0] = s->hlua[1] = NULL; + if (s->txn) http_destroy_txn(s); @@ -2367,7 +2369,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) /* shutdown(write) pending */ if (unlikely((scb->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == SC_FL_SHUT_WANTED && - (!co_data(req) || (req->flags & CF_WRITE_TIMEOUT)))) { + ((!co_data(req) && !sc_ep_have_ff_data(scb)) || (req->flags & CF_WRITE_TIMEOUT)))) { if (scf->flags & SC_FL_ERROR) scb->flags |= SC_FL_NOLINGER; sc_shutdown(scb); @@ -2475,7 +2477,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) /* shutdown(write) pending */ if (unlikely((scf->flags & (SC_FL_SHUT_DONE|SC_FL_SHUT_WANTED)) == SC_FL_SHUT_WANTED && - (!co_data(res) || (res->flags & CF_WRITE_TIMEOUT)))) { + ((!co_data(res) && !sc_ep_have_ff_data(scf)) || (res->flags & CF_WRITE_TIMEOUT)))) { sc_shutdown(scf); } @@ -2681,6 +2683,20 @@ void sess_change_server(struct stream *strm, struct server *newsrv) { struct server *oldsrv = strm->srv_conn; + /* Dynamic servers may be deleted during process lifetime. This + * operation is always conducted under thread isolation. Several + * conditions prevent deletion, one of them is if server streams list + * is not empty. sess_change_server() uses stream_add_srv_conn() to + * ensure the latter condition. + * + * A race condition could exist for stream which referenced a server + * instance (s->target) without registering itself in its server list. + * This is notably the case for SF_DIRECT streams which referenced a + * server earlier during process_stream(). However at this time the + * code is deemed safe as process_stream() cannot be rescheduled before + * invocation of sess_change_server(). + */ + if (oldsrv == newsrv) return; |