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 90f4614..c4d956e 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -2243,6 +2243,16 @@
/* 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 @@
}
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 @@
goto out;
}
+ 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);
+
- if (check->cs)
+
cs_destroy(check->cs);
+ }
check->cs = cs;
conn = cs->conn;