]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
CLEANUP: sock: always perform last connection updates before wakeup
authorWilly Tarreau <w@1wt.eu>
Thu, 2 Mar 2023 14:07:51 +0000 (15:07 +0100)
committerWilly Tarreau <w@1wt.eu>
Wed, 8 Mar 2023 15:07:32 +0000 (16:07 +0100)
Normally the task_wakeup() in sock_conn_io_cb() is expected to
happen on the same thread the FD is attached to. But due to the
way the code was arranged in the past (with synchronous callbacks)
we continue to update connections after the wakeup, which always
makes the reader have to think deeply whether it's possible or not
to call another thread there. Let's just move the tasklet_wakeup()
at the end to make sure there's no problem with that.

src/sock.c

index 1482c1a4f6a64afa015aff97c7f2f868bdf90194..3bc92fbfcf7ce7c06264e109e1c5ceeaa7e65604 100644 (file)
@@ -818,6 +818,7 @@ void sock_conn_iocb(int fd)
        struct connection *conn = fdtab[fd].owner;
        unsigned int flags;
        int need_wake = 0;
+       struct tasklet *t;
 
        if (unlikely(!conn)) {
                activity[tid].conn_dead++;
@@ -845,11 +846,12 @@ void sock_conn_iocb(int fd)
                 */
                flags = 0;
                if (conn->subs && conn->subs->events & SUB_RETRY_SEND) {
+                       t = conn->subs->tasklet;
                        need_wake = 0; // wake will be called after this I/O
-                       tasklet_wakeup(conn->subs->tasklet);
                        conn->subs->events &= ~SUB_RETRY_SEND;
                        if (!conn->subs->events)
                                conn->subs = NULL;
+                       tasklet_wakeup(t);
                }
                fd_stop_send(fd);
        }
@@ -865,11 +867,12 @@ void sock_conn_iocb(int fd)
                 */
                flags = 0;
                if (conn->subs && conn->subs->events & SUB_RETRY_RECV) {
+                       t = conn->subs->tasklet;
                        need_wake = 0; // wake will be called after this I/O
-                       tasklet_wakeup(conn->subs->tasklet);
                        conn->subs->events &= ~SUB_RETRY_RECV;
                        if (!conn->subs->events)
                                conn->subs = NULL;
+                       tasklet_wakeup(t);
                }
                fd_stop_recv(fd);
        }