mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 07:07:04 +02:00
MINOR: hlua: emit a log instead of an alert for aborted actions due to unavailable yield
As reported by Chris Staite in GH #3002, trying to yield from a Lua action during a client disconnect causes the script to be interrupted (which is expected) and an alert to be emitted with the error: "Lua function '%s': yield not allowed". While this error is well suited for cases where the yield is not expected at all (ie: when context doesn't allow it) and results from a yield misuse in the Lua script, it isn't the case when the yield is exceptionnally not available due to an abort or error in the request/response processing. Because of that we raise an alert but the user cannot do anything about it (the script is correct), so it is confusing and polluting the logs. In this patch we introduce the ACT_OPT_FINAL_EARLY flag which is a complementary flag to ACT_OPT_FIRST. This flag is set when the ACT_OPT_FIRST is set earlier than normal (due to error/abort). hlua_action() then checks for this flag to decide whether an error (alert) or a simple log message should be emitted when the yield is not available. It should solve GH #3002. Thanks to Chris Staite (@chrisstaite-menlo) for having reported the issue and suggested a solution.
This commit is contained in:
parent
20a82027ce
commit
c0f6024854
@ -66,7 +66,8 @@ enum act_parse_ret {
|
||||
enum act_opt {
|
||||
ACT_OPT_NONE = 0x00000000, /* no flag */
|
||||
ACT_OPT_FINAL = 0x00000001, /* last call, cannot yield */
|
||||
ACT_OPT_FIRST = 0x00000002, /* first call for this action */
|
||||
ACT_OPT_FINAL_EARLY = 0x00000002, /* set in addition to ACT_OPT_FINAL if last call occurs earlier than normal due to unexpected IO/error */
|
||||
ACT_OPT_FIRST = 0x00000004, /* first call for this action */
|
||||
};
|
||||
|
||||
/* Flags used to describe the action. */
|
||||
|
20
src/hlua.c
20
src/hlua.c
@ -11005,8 +11005,24 @@ static enum act_return hlua_action(struct act_rule *rule, struct proxy *px,
|
||||
case HLUA_E_YIELD:
|
||||
err_yield:
|
||||
act_ret = ACT_RET_CONT;
|
||||
SEND_ERR(px, "Lua function '%s': yield not allowed.\n",
|
||||
rule->arg.hlua_rule->fcn->name);
|
||||
if (flags & ACT_OPT_FINAL_EARLY) {
|
||||
char *msg = NULL;
|
||||
|
||||
/* yield not allowed, but it is only caused because ruleset was ended earlier
|
||||
* than expected, so it is not a misuse of yield in the Lua script: simply emit
|
||||
* a log
|
||||
*/
|
||||
memprintf(&msg, "Lua function '%s': unable to yield, aborted Lua execution.\n",
|
||||
rule->arg.hlua_rule->fcn->name);
|
||||
if (msg)
|
||||
hlua_sendlog(px, LOG_WARNING, msg);
|
||||
ha_free(&msg);
|
||||
}
|
||||
else {
|
||||
/* invalid yield use */
|
||||
SEND_ERR(px, "Lua function '%s': yield not allowed.\n",
|
||||
rule->arg.hlua_rule->fcn->name);
|
||||
}
|
||||
goto end;
|
||||
|
||||
case HLUA_E_ERR:
|
||||
|
@ -2757,7 +2757,7 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
|
||||
if ((s->scf->flags & SC_FL_ERROR) ||
|
||||
((s->scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) &&
|
||||
(px->options & PR_O_ABRT_CLOSE)))
|
||||
act_opts |= ACT_OPT_FINAL;
|
||||
act_opts |= ACT_OPT_FINAL | ACT_OPT_FINAL_EARLY;
|
||||
|
||||
/* If "the current_rule_list" match the executed rule list, we are in
|
||||
* resume condition. If a resume is needed it is always in the action
|
||||
@ -2945,7 +2945,7 @@ static enum rule_result http_res_get_intercept_rule(struct proxy *px, struct lis
|
||||
if ((s->scf->flags & SC_FL_ERROR) ||
|
||||
((s->scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) &&
|
||||
(px->options & PR_O_ABRT_CLOSE)))
|
||||
act_opts |= ACT_OPT_FINAL;
|
||||
act_opts |= ACT_OPT_FINAL | ACT_OPT_FINAL_EARLY;
|
||||
|
||||
/* If "the current_rule_list" match the executed rule list, we are in
|
||||
* resume condition. If a resume is needed it is always in the action
|
||||
|
@ -124,7 +124,7 @@ int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit)
|
||||
partial = SMP_OPT_FINAL;
|
||||
/* Action may yield while the inspect_delay is not expired and there is no read error */
|
||||
if ((s->scf->flags & SC_FL_ERROR) || !s->be->tcp_req.inspect_delay || tick_is_expired(s->rules_exp, now_ms))
|
||||
act_opts |= ACT_OPT_FINAL;
|
||||
act_opts |= ACT_OPT_FINAL | ACT_OPT_FINAL_EARLY;
|
||||
}
|
||||
else
|
||||
partial = 0;
|
||||
@ -337,7 +337,7 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
partial = SMP_OPT_FINAL;
|
||||
/* Action may yield while the inspect_delay is not expired and there is no read error */
|
||||
if ((s->scb->flags & SC_FL_ERROR) || !s->be->tcp_rep.inspect_delay || tick_is_expired(s->rules_exp, now_ms))
|
||||
act_opts |= ACT_OPT_FINAL;
|
||||
act_opts |= ACT_OPT_FINAL | ACT_OPT_FINAL_EARLY;
|
||||
}
|
||||
else
|
||||
partial = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user