Skip to content

Commit 537f20e

Browse files
committed
MINOR: stream: Save the entity waiting to continue its processing
When a rule or a filter yields because it waits for something to be able to continue its processing, this entity is saved in the stream. If an error or a timeout occurred, info on this entity may be retrieved via the "waiting_entity" sample fetch, for instance to dump it in the logs. This info may be useful to found root cause of some bugs because it is a way to know the processing was temporarily stopped. This may explain timeouts for instance. The sample fetch is not documented yet.
1 parent 53de6da commit 537f20e

File tree

5 files changed

+82
-3
lines changed

5 files changed

+82
-3
lines changed

include/haproxy/stream-t.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,11 @@ struct stream {
295295
int type; /* entity type (0: undef, 1: rule, 2: filter) */
296296
} last_entity; /* last evaluated entity that interrupted processing */
297297

298+
struct {
299+
void *ptr; /* Pointer on the entity (def: NULL) */
300+
int type; /* entity type (0: undef, 1: rule, 2: filter) */
301+
} waiting_entity; /* The entity waiting to continue its processing and interrupted by an error/timeout */
302+
298303
unsigned int stream_epoch; /* copy of stream_epoch when the stream was created */
299304
struct hlua *hlua[2]; /* lua runtime context (0: global, 1: per-thread) */
300305

src/filters.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,14 @@ static int handle_analyzer_result(struct stream *s, struct channel *chn, unsigne
5757
do { \
5858
struct filter *filter; \
5959
\
60-
if (strm_flt(strm)->current[CHN_IDX(chn)]) { \
60+
if (strm_flt(strm)->current[CHN_IDX(chn)]) { \
6161
filter = strm_flt(strm)->current[CHN_IDX(chn)]; \
62-
strm_flt(strm)->current[CHN_IDX(chn)] = NULL; \
62+
strm_flt(strm)->current[CHN_IDX(chn)] = NULL; \
63+
if (!(chn_prod(chn)->flags & SC_FL_ERROR) && \
64+
!(chn->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT))) { \
65+
(strm)->waiting_entity.type = 0; \
66+
(strm)->waiting_entity.ptr = NULL; \
67+
} \
6368
goto resume_execution; \
6469
} \
6570
\
@@ -72,7 +77,11 @@ static int handle_analyzer_result(struct stream *s, struct channel *chn, unsigne
7277

7378
#define BREAK_EXECUTION(strm, chn, label) \
7479
do { \
75-
if (ret < 0) { \
80+
if (ret == 0) { \
81+
s->waiting_entity.type = 2; \
82+
s->waiting_entity.ptr = filter; \
83+
} \
84+
else if (ret < 0) { \
7685
(strm)->last_entity.type = 2; \
7786
(strm)->last_entity.ptr = filter; \
7887
} \

src/http_ana.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2734,6 +2734,11 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
27342734
(px->options & PR_O_ABRT_CLOSE)))
27352735
act_opts |= ACT_OPT_FINAL;
27362736

2737+
if (!(s->scf->flags & SC_FL_ERROR) & !(s->req.flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT))) {
2738+
s->waiting_entity.type = 0;
2739+
s->waiting_entity.ptr = NULL;
2740+
}
2741+
27372742
switch (rule->action_ptr(rule, px, sess, s, act_opts)) {
27382743
case ACT_RET_CONT:
27392744
break;
@@ -2753,6 +2758,8 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
27532758
rule_ret = HTTP_RULE_RES_ERROR;
27542759
goto end;
27552760
}
2761+
s->waiting_entity.type = 1;
2762+
s->waiting_entity.ptr = rule;
27562763
rule_ret = HTTP_RULE_RES_YIELD;
27572764
goto end;
27582765
case ACT_RET_ERR:
@@ -2908,6 +2915,11 @@ static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct lis
29082915
(px->options & PR_O_ABRT_CLOSE)))
29092916
act_opts |= ACT_OPT_FINAL;
29102917

2918+
if (!(s->scb->flags & SC_FL_ERROR) & !(s->res.flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT))) {
2919+
s->waiting_entity.type = 0;
2920+
s->waiting_entity.ptr = NULL;
2921+
}
2922+
29112923
switch (rule->action_ptr(rule, px, sess, s, act_opts)) {
29122924
case ACT_RET_CONT:
29132925
break;
@@ -2927,6 +2939,8 @@ static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct lis
29272939
rule_ret = HTTP_RULE_RES_ERROR;
29282940
goto end;
29292941
}
2942+
s->waiting_entity.type = 1;
2943+
s->waiting_entity.ptr = rule;
29302944
rule_ret = HTTP_RULE_RES_YIELD;
29312945
goto end;
29322946
case ACT_RET_ERR:

src/stream.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,8 @@ struct stream *stream_new(struct session *sess, struct stconn *sc, struct buffer
391391
s->rules_exp = TICK_ETERNITY;
392392
s->last_entity.type = 0;
393393
s->last_entity.ptr = NULL;
394+
s->waiting_entity.type = 0;
395+
s->waiting_entity.ptr = NULL;
394396

395397
s->stkctr = NULL;
396398
if (pool_head_stk_ctr) {
@@ -4158,6 +4160,41 @@ static int smp_fetch_last_entity(const struct arg *args, struct sample *smp, con
41584160
return 1;
41594161
}
41604162

4163+
static int smp_fetch_waiting_entity(const struct arg *args, struct sample *smp, const char *km, void *private)
4164+
{
4165+
smp->flags = SMP_F_VOL_TXN;
4166+
smp->data.type = SMP_T_STR;
4167+
if (!smp->strm)
4168+
return 0;
4169+
4170+
if (smp->strm->waiting_entity.type == 1) {
4171+
struct act_rule *rule = smp->strm->waiting_entity.ptr;
4172+
struct buffer *trash = get_trash_chunk();
4173+
4174+
trash->data = snprintf(trash->area, trash->size, "%s:%d", rule->conf.file, rule->conf.line);
4175+
smp->data.u.str = *trash;
4176+
}
4177+
else if (smp->strm->waiting_entity.type == 2) {
4178+
struct filter *filter = smp->strm->waiting_entity.ptr;
4179+
4180+
if (FLT_ID(filter)) {
4181+
smp->flags |= SMP_F_CONST;
4182+
smp->data.u.str.area = (char *)FLT_ID(filter);
4183+
smp->data.u.str.data = strlen(FLT_ID(filter));
4184+
}
4185+
else {
4186+
struct buffer *trash = get_trash_chunk();
4187+
4188+
trash->data = snprintf(trash->area, trash->size, "%p", filter->config);
4189+
smp->data.u.str = *trash;
4190+
}
4191+
}
4192+
else
4193+
return 0;
4194+
4195+
return 1;
4196+
}
4197+
41614198
static int smp_fetch_sess_term_state(const struct arg *args, struct sample *smp, const char *km, void *private)
41624199
{
41634200
struct buffer *trash = get_trash_chunk();
@@ -4226,6 +4263,7 @@ static struct sample_fetch_kw_list smp_kws = {ILH, {
42264263
{ "txn.id32", smp_fetch_id32, 0, NULL, SMP_T_SINT, SMP_USE_INTRN, },
42274264
{ "txn.redispatched", smp_fetch_redispatched, 0, NULL, SMP_T_BOOL, SMP_USE_L4SRV, },
42284265
{ "txn.sess_term_state",smp_fetch_sess_term_state, 0, NULL, SMP_T_STR, SMP_USE_INTRN, },
4266+
{ "waiting_entity", smp_fetch_waiting_entity, 0, NULL, SMP_T_STR, SMP_USE_INTRN, },
42294267
{ NULL, NULL, 0, 0, 0 },
42304268
}};
42314269

src/tcp_rules.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit)
137137
if (s->current_rule) {
138138
rule = s->current_rule;
139139
s->current_rule = NULL;
140+
if (!(req->flags & SC_FL_ERROR) && !(req->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT))) {
141+
s->waiting_entity.type = 0;
142+
s->waiting_entity.ptr = NULL;
143+
}
140144
if ((def_rules && s->current_rule_list == def_rules) || s->current_rule_list == rules)
141145
goto resume_execution;
142146
}
@@ -179,6 +183,8 @@ int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit)
179183
s->last_entity.ptr = rule;
180184
goto internal;
181185
}
186+
s->waiting_entity.type = 1;
187+
s->waiting_entity.ptr = rule;
182188
goto missing_data;
183189
case ACT_RET_DENY:
184190
s->last_entity.type = 1;
@@ -321,6 +327,10 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
321327
if (s->current_rule) {
322328
rule = s->current_rule;
323329
s->current_rule = NULL;
330+
if (!(rep->flags & SC_FL_ERROR) && !(rep->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT))) {
331+
s->waiting_entity.type = 0;
332+
s->waiting_entity.ptr = NULL;
333+
}
324334
if ((def_rules && s->current_rule_list == def_rules) || s->current_rule_list == rules)
325335
goto resume_execution;
326336
}
@@ -343,6 +353,7 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
343353
if (ret) {
344354
act_opts |= ACT_OPT_FIRST;
345355
resume_execution:
356+
346357
/* Always call the action function if defined */
347358
if (rule->action_ptr) {
348359
switch (rule->action_ptr(rule, s->be, s->sess, s, act_opts)) {
@@ -363,6 +374,8 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
363374
s->last_entity.ptr = rule;
364375
goto internal;
365376
}
377+
s->waiting_entity.type = 1;
378+
s->waiting_entity.ptr = rule;
366379
channel_dont_close(rep);
367380
goto missing_data;
368381
case ACT_RET_DENY:

0 commit comments

Comments
 (0)