]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: checks: Make sure we unsubscribe before calling cs_destroy().
authorOlivier Houchard <ohouchard@haproxy.com>
Fri, 31 May 2019 17:20:36 +0000 (19:20 +0200)
committerOlivier Houchard <cognet@ci0.org>
Wed, 5 Jun 2019 16:03:38 +0000 (18:03 +0200)
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.

src/checks.c

index 90f46147717dd708368f3f2862ec7a20b2b898f5..c4d956ee04d5c9d6f0154ea10f0d2bf335b5a4a2 100644 (file)
@@ -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;