From: Olivier Houchard Date: Fri, 31 May 2019 17:20:36 +0000 (+0200) Subject: MEDIUM: checks: Make sure we unsubscribe before calling cs_destroy(). X-Git-Tag: v2.0-dev6~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=49065544d08b2432338cf861c59a7647b7f5546b;p=thirdparty%2Fhaproxy.git MEDIUM: checks: Make sure we unsubscribe before calling cs_destroy(). When we want to destroy the conn_stream for some reason, usually on error, make sure we unsubscribed before doing so. If we subsscribed, the xprt may ultimately wake our tasklet on close, aand the check tasklet doesn't expect it ot happen when we have no longer any conn_stream. --- diff --git a/src/checks.c b/src/checks.c index 90f4614771..c4d956ee04 100644 --- a/src/checks.c +++ b/src/checks.c @@ -2243,6 +2243,16 @@ static struct task *process_chk_conn(struct task *t, void *context, unsigned sho /* here, we have seen a synchronous error, no fd was allocated */ if (cs) { + if (check->wait_list.events) + cs->conn->xprt->unsubscribe(cs->conn, + cs->conn->xprt_ctx, + check->wait_list.events, + &check->wait_list); + /* We may have been scheduled to run, and the + * I/O handler expects to have a cs, so remove + * the tasklet + */ + task_remove_from_tasklet_list((struct task *)check->wait_list.task); cs_destroy(cs); cs = check->cs = NULL; conn = NULL; @@ -2297,6 +2307,16 @@ static struct task *process_chk_conn(struct task *t, void *context, unsigned sho } if (cs) { + if (check->wait_list.events) + cs->conn->xprt->unsubscribe(cs->conn, + cs->conn->xprt_ctx, + check->wait_list.events, + &check->wait_list); + /* We may have been scheduled to run, and the + * I/O handler expects to have a cs, so remove + * the tasklet + */ + task_remove_from_tasklet_list((struct task *)check->wait_list.task); cs_destroy(cs); cs = check->cs = NULL; conn = NULL; @@ -2803,8 +2823,21 @@ static int tcpcheck_main(struct check *check) goto out; } - if (check->cs) + if (check->cs) { + if (check->wait_list.events) + cs->conn->xprt->unsubscribe(cs->conn, + cs->conn->xprt_ctx, + check->wait_list.events, + &check->wait_list); + /* We may have been scheduled to run, and the + * I/O handler expects to have a cs, so remove + * the tasklet + */ + task_remove_from_tasklet_list((struct task *)check->wait_list.task); + + cs_destroy(check->cs); + } check->cs = cs; conn = cs->conn;