]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Always enqueue isc__nm_tcp_resumeread()
authorOndřej Surý <ondrej@isc.org>
Thu, 6 Jan 2022 12:03:39 +0000 (13:03 +0100)
committerEvan Hunt <each@isc.org>
Thu, 6 Jan 2022 18:34:04 +0000 (10:34 -0800)
The isc__nm_tcp_resumeread() was using maybe_enqueue function to enqueue
netmgr event which could case the read callback to be executed
immediately if there was enough data waiting in the TCP queue.

If such thing would happen, the read callback would be called before the
previous read callback was finished and the worker receive buffer would
be still marked "in use" causing a assertion failure.

This would affect only raw TCP channels, e.g. rndc and http statistics.

lib/isc/netmgr/tcp.c

index b818f41a20038cb296913596d0e1c2d1b7f19f51..872d96fe6a0cf21563a8edf179aa1b64d35814a1 100644 (file)
@@ -814,6 +814,7 @@ isc__nm_tcp_resumeread(isc_nmhandle_t *handle) {
 
        isc__netievent_tcpstartread_t *ievent = NULL;
        isc_nmsocket_t *sock = handle->sock;
+       isc__networker_t *worker = &sock->mgr->workers[sock->tid];
 
        REQUIRE(sock->tid == isc_nm_tid());
 
@@ -835,8 +836,18 @@ isc__nm_tcp_resumeread(isc_nmhandle_t *handle) {
 
        ievent = isc__nm_get_netievent_tcpstartread(sock->mgr, sock);
 
-       isc__nm_maybe_enqueue_ievent(&sock->mgr->workers[sock->tid],
-                                    (isc__netievent_t *)ievent);
+       if (worker->recvbuf_inuse) {
+               /*
+                * If we happen to call the resumeread from inside the receive
+                * callback, the worker->recvbuf might still be in use, so we
+                * need to force enqueue the next read event.
+                */
+               isc__nm_enqueue_ievent(worker, (isc__netievent_t *)ievent);
+
+       } else {
+               isc__nm_maybe_enqueue_ievent(worker,
+                                            (isc__netievent_t *)ievent);
+       }
 }
 
 void