diff --git a/include/proto/stream.h b/include/proto/stream.h index d4f82136b..1fea1ab1c 100644 --- a/include/proto/stream.h +++ b/include/proto/stream.h @@ -88,7 +88,8 @@ static inline enum obj_type *strm_orig(const struct stream *strm) /* Remove the refcount from the stream to the tracked counters, and clear the * pointer to ensure this is only performed once. The caller is responsible for - * ensuring that the pointer is valid first. + * ensuring that the pointer is valid first. We must be extremely careful not + * to touch the entries we inherited from the session. */ static inline void stream_store_counters(struct stream *s) { @@ -98,6 +99,10 @@ static inline void stream_store_counters(struct stream *s) for (i = 0; i < MAX_SESS_STKCTR; i++) { if (!stkctr_entry(&s->stkctr[i])) continue; + + if (stkctr_entry(&s->sess->stkctr[i])) + continue; + ptr = stktable_data_ptr(s->stkctr[i].table, stkctr_entry(&s->stkctr[i]), STKTABLE_DT_CONN_CUR); if (ptr) stktable_data_cast(ptr, conn_cur)--; @@ -109,7 +114,8 @@ static inline void stream_store_counters(struct stream *s) /* Remove the refcount from the stream counters tracked at the content level if * any, and clear the pointer to ensure this is only performed once. The caller - * is responsible for ensuring that the pointer is valid first. + * is responsible for ensuring that the pointer is valid first. We must be + * extremely careful not to touch the entries we inherited from the session. */ static inline void stream_stop_content_counters(struct stream *s) { @@ -120,6 +126,9 @@ static inline void stream_stop_content_counters(struct stream *s) if (!stkctr_entry(&s->stkctr[i])) continue; + if (stkctr_entry(&s->sess->stkctr[i])) + continue; + if (!(stkctr_flags(&s->stkctr[i]) & STKCTR_TRACK_CONTENT)) continue; diff --git a/src/stream.c b/src/stream.c index dadb80f70..6c1f7ab84 100644 --- a/src/stream.c +++ b/src/stream.c @@ -71,7 +71,6 @@ struct stream *stream_new(struct session *sess, struct task *t, enum obj_type *o struct stream *s; struct connection *conn = objt_conn(origin); struct appctx *appctx = objt_appctx(origin); - int i; if (unlikely((s = pool_alloc2(pool2_stream)) == NULL)) return s; @@ -108,13 +107,13 @@ struct stream *stream_new(struct session *sess, struct task *t, enum obj_type *o s->current_rule_list = NULL; s->current_rule = NULL; - /* Copy SC counters for the stream. Each SC counter will be used by - * the stream, so we need to increment the refcount. + /* Copy SC counters for the stream. We don't touch refcounts because + * any reference we have is inherited from the session. Since the stream + * doesn't exist without the session, the session's existence guarantees + * we don't lose the entry. During the store operation, the stream won't + * touch these ones. */ memcpy(s->stkctr, sess->stkctr, sizeof(s->stkctr)); - for (i = 0; i < MAX_SESS_STKCTR; i++) - if (stkctr_entry(&s->stkctr[i])) - stkctr_entry(&s->stkctr[i])->ref_cnt++; s->sess = sess; s->si[0].flags = SI_FL_NONE;