]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stream: Display the currently running filter per channel in stream dump
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 4 Mar 2026 10:03:01 +0000 (11:03 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Thu, 5 Mar 2026 14:34:47 +0000 (15:34 +0100)
Since the 3.1, when stream's info are dump, it is possible to print the
yielding filter on each channel, if any. It was useful to detect buggy
filter on spinning loop. But it is not possible to detect a filter consuming
too much CPU per-execution. We can see a filter was executing in the
backtrace reported by the watchdog, but we are unable to spot the specific
one.

Thanks to this patch, it is now possible. When a dump is emitted, the
running or yield filters on each channel are now displayed with their
current state (RUNNING or YIELDING).

This patch could be backported as far as 3.2 because it could be useful to
spot issues. But the filter API was slightly refactored in 3.4, so this
patch should be adapted.

src/filters.c
src/stream.c

index 9775348bc9bae16101ad393f2836e88a6b03dd36..842150fff00bbca577a4328d98b5e1a39187eb52 100644 (file)
@@ -69,15 +69,16 @@ static inline struct filter *resume_filter_list_start(struct stream *strm, struc
 
        if (chn->flt.current) {
                filter = chn->flt.current;
-               chn->flt.current = NULL;
                if (!(chn_prod(chn)->flags & SC_FL_ERROR) &&
                    !(chn->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT))) {
                        (strm)->waiting_entity.type = STRM_ENTITY_NONE;
                        (strm)->waiting_entity.ptr = NULL;
                }
        }
-       else
+       else {
                filter = flt_list_start(strm, chn);
+               chn->flt.current = filter;
+       }
 
        return filter;
 }
@@ -85,22 +86,24 @@ static inline struct filter *resume_filter_list_start(struct stream *strm, struc
 static inline struct filter *resume_filter_list_next(struct stream *strm, struct channel *chn,
                                                      struct filter *filter)
 {
-       /* simply an alias to flt_list_next() */
-       return flt_list_next(strm, chn, filter);
+       filter = flt_list_next(strm, chn, filter);
+       chn->flt.current = filter;
+       return filter;
 }
 
 static inline void resume_filter_list_break(struct stream *strm, struct channel *chn,
                                             struct filter *filter, int ret)
 {
+       chn->flt.current = NULL;
        if (ret == 0) {
                strm->waiting_entity.type = STRM_ENTITY_FILTER;
                strm->waiting_entity.ptr  = filter;
+               chn->flt.current = filter;
        }
        else if (ret < 0) {
                strm->last_entity.type = STRM_ENTITY_FILTER;
                strm->last_entity.ptr = filter;
        }
-       chn->flt.current = filter;
 }
 
 /* List head of all known filter keywords */
index b72788ac05ab746176f1fa86c9965a0ea96a43ff..3a0c6b806ad371cb6591a80ab476428c0be5937e 100644 (file)
@@ -3801,8 +3801,9 @@ static void __strm_dump_to_buffer(struct buffer *buf, const struct show_sess_ctx
        if (HAS_FILTERS(strm) && strm->req.flt.current) {
                const struct filter *flt = strm->req.flt.current;
 
-               chunk_appendf(buf, "%s      current_filter=%p (id=\"%s\" flags=0x%x pre=0x%x post=0x%x) \n", pfx,
-                             flt, flt->config->id, flt->flags, flt->pre_analyzers, flt->post_analyzers);
+               chunk_appendf(buf, "%s      current_filter=%p (id=\"%s\" flags=0x%x pre=0x%x post=0x%x %s) \n", pfx,
+                             flt, flt->config->id, flt->flags, flt->pre_analyzers, flt->post_analyzers,
+                             (flt == strm->waiting_entity.ptr) ? "YIELDING" : "RUNNING");
        }
 
        chunk_appendf(buf,
@@ -3834,8 +3835,9 @@ static void __strm_dump_to_buffer(struct buffer *buf, const struct show_sess_ctx
        if (HAS_FILTERS(strm) && strm->res.flt.current) {
                const struct filter *flt = strm->res.flt.current;
 
-               chunk_appendf(buf, "%s      current_filter=%p (id=\"%s\" flags=0x%x pre=0x%x post=0x%x) \n", pfx,
-                             flt, flt->config->id, flt->flags, flt->pre_analyzers, flt->post_analyzers);
+               chunk_appendf(buf, "%s      current_filter=%p (id=\"%s\" flags=0x%x pre=0x%x post=0x%x %s) \n", pfx,
+                             flt, flt->config->id, flt->flags, flt->pre_analyzers, flt->post_analyzers,
+                             (flt == strm->waiting_entity.ptr) ? "YIELDING" : "RUNNING");
        }
 
        if (strm->current_rule_list && strm->current_rule) {