]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix #356: deadlock when listening tcp.
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 2 Dec 2020 09:10:27 +0000 (10:10 +0100)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Wed, 2 Dec 2020 09:10:27 +0000 (10:10 +0100)
doc/Changelog
services/listen_dnsport.c
util/netevent.c
util/netevent.h

index 1e895f9f2321f3f66eac1833f895d2c09640461d..405060fc4b0384d6d7dc6017f6ba50ec2f9e6b5f 100644 (file)
@@ -2,6 +2,7 @@
        - Fix #360: for the additionally reported TCP Fast Open makes TCP
          connections fail, in that case we print a hint that this is
          happening with the error in the logs.
+       - Fix #356: deadlock when listening tcp.
 
 1 December 2020: Wouter
        - Fix #358: Squelch udp connect 'no route to host' errors on low
index d63c0e0aab00e1c89dc342db7691d83890ae708f..709c9e6ce698b27209d923be2fc8b4ee8ed839d7 100644 (file)
@@ -1821,12 +1821,12 @@ tcp_req_info_setup_listen(struct tcp_req_info* req)
                req->cp->tcp_is_reading = 0;
                comm_point_stop_listening(req->cp);
                comm_point_start_listening(req->cp, -1,
-                       req->cp->tcp_timeout_msec);
+                       adjusted_tcp_timeout(req->cp));
        } else if(rd) {
                req->cp->tcp_is_reading = 1;
                comm_point_stop_listening(req->cp);
                comm_point_start_listening(req->cp, -1,
-                       req->cp->tcp_timeout_msec);
+                       adjusted_tcp_timeout(req->cp));
                /* and also read it (from SSL stack buffers), so
                 * no event read event is expected since the remainder of
                 * the TLS frame is sitting in the buffers. */
@@ -1834,7 +1834,7 @@ tcp_req_info_setup_listen(struct tcp_req_info* req)
        } else {
                comm_point_stop_listening(req->cp);
                comm_point_start_listening(req->cp, -1,
-                       req->cp->tcp_timeout_msec);
+                       adjusted_tcp_timeout(req->cp));
                comm_point_listen_for_rw(req->cp, 0, 0);
        }
 }
@@ -1947,7 +1947,7 @@ tcp_req_info_handle_readdone(struct tcp_req_info* req)
        send_it:
                c->tcp_is_reading = 0;
                comm_point_stop_listening(c);
-               comm_point_start_listening(c, -1, c->tcp_timeout_msec);
+               comm_point_start_listening(c, -1, adjusted_tcp_timeout(c));
                return;
        }
        req->in_worker_handle = 0;
@@ -2065,7 +2065,7 @@ tcp_req_info_send_reply(struct tcp_req_info* req)
                /* switch to listen to write events */
                comm_point_stop_listening(req->cp);
                comm_point_start_listening(req->cp, -1,
-                       req->cp->tcp_timeout_msec);
+                       adjusted_tcp_timeout(req->cp));
                return;
        }
        /* queue up the answer behind the others already pending */
index 1a5d228927702de01c0d6a225510054003c1f542..98796a78815084833971d6c7ce8e16eaa09c0f99 100644 (file)
@@ -762,6 +762,13 @@ comm_point_udp_callback(int fd, short event, void* arg)
        }
 }
 
+int adjusted_tcp_timeout(struct comm_point* c)
+{
+       if(c->tcp_timeout_msec < TCP_QUERY_TIMEOUT_MINIMUM)
+               return TCP_QUERY_TIMEOUT_MINIMUM;
+       return c->tcp_timeout_msec;
+}
+
 /** Use a new tcp handler for new query fd, set to read query */
 static void
 setup_tcp_handler(struct comm_point* c, int fd, int cur, int max) 
@@ -795,10 +802,7 @@ setup_tcp_handler(struct comm_point* c, int fd, int cur, int max)
                c->tcp_timeout_msec /= 500;
        else if (handler_usage > 80)
                c->tcp_timeout_msec = 0;
-       comm_point_start_listening(c, fd,
-               c->tcp_timeout_msec < TCP_QUERY_TIMEOUT_MINIMUM
-                       ? TCP_QUERY_TIMEOUT_MINIMUM
-                       : c->tcp_timeout_msec);
+       comm_point_start_listening(c, fd, adjusted_tcp_timeout(c));
 }
 
 void comm_base_handle_slow_accept(int ATTR_UNUSED(fd),
@@ -1108,10 +1112,11 @@ tcp_callback_writer(struct comm_point* c)
                        if( (*c->callback)(c, c->cb_arg, NETEVENT_PKT_WRITTEN,
                                &c->repinfo) ) {
                                comm_point_start_listening(c, -1,
-                                       c->tcp_timeout_msec);
+                                       adjusted_tcp_timeout(c));
                        }
                } else {
-                       comm_point_start_listening(c, -1, c->tcp_timeout_msec);
+                       comm_point_start_listening(c, -1,
+                                       adjusted_tcp_timeout(c));
                }
        }
 }
@@ -1132,7 +1137,8 @@ tcp_callback_reader(struct comm_point* c)
                        comm_point_stop_listening(c);
                fptr_ok(fptr_whitelist_comm_point(c->callback));
                if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo) ) {
-                       comm_point_start_listening(c, -1, c->tcp_timeout_msec);
+                       comm_point_start_listening(c, -1,
+                                       adjusted_tcp_timeout(c));
                }
        }
 }
@@ -2656,7 +2662,7 @@ comm_point_http2_handle_read(int ATTR_UNUSED(fd), struct comm_point* c)
        if(nghttp2_session_want_write(c->h2_session->session)) {
                c->tcp_is_reading = 0;
                comm_point_stop_listening(c);
-               comm_point_start_listening(c, -1, c->tcp_timeout_msec);
+               comm_point_start_listening(c, -1, adjusted_tcp_timeout(c));
        } else if(!nghttp2_session_want_read(c->h2_session->session))
                return 0; /* connection can be closed */
        return 1;
@@ -2974,7 +2980,7 @@ comm_point_http2_handle_write(int ATTR_UNUSED(fd), struct comm_point* c)
        if(nghttp2_session_want_read(c->h2_session->session)) {
                c->tcp_is_reading = 1;
                comm_point_stop_listening(c);
-               comm_point_start_listening(c, -1, c->tcp_timeout_msec);
+               comm_point_start_listening(c, -1, adjusted_tcp_timeout(c));
        } else if(!nghttp2_session_want_write(c->h2_session->session))
                return 0; /* connection can be closed */
        return 1;
@@ -3932,11 +3938,11 @@ comm_point_send_reply(struct comm_reply *repinfo)
                        repinfo->c->tcp_is_reading = 0;
                        comm_point_stop_listening(repinfo->c);
                        comm_point_start_listening(repinfo->c, -1,
-                               repinfo->c->tcp_timeout_msec);
+                               adjusted_tcp_timeout(repinfo->c));
                        return;
                } else {
                        comm_point_start_listening(repinfo->c, -1,
-                               repinfo->c->tcp_timeout_msec);
+                               adjusted_tcp_timeout(repinfo->c));
                }
        }
 }
index daa954b6492fd3b3c8c93c4605ead1ced1adcfcd..266a74ff333e41de63f2e70e1674dda81210b92d 100644 (file)
@@ -661,6 +661,16 @@ void comm_point_start_listening(struct comm_point* c, int newfd, int msec);
  */
 void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr);
 
+/**
+ * For TCP handlers that use c->tcp_timeout_msec, this routine adjusts
+ * it with the minimum.  Otherwise, a 0 value advertised without the
+ * minimum applied moves to a 0 in comm_point_start_listening and that
+ * routine treats it as no timeout, listen forever, which is not wanted.
+ * @param c: comm point to use the tcp_timeout_msec of.
+ * @return adjusted tcp_timeout_msec value with the minimum if smaller.
+ */
+int adjusted_tcp_timeout(struct comm_point* c);
+
 /**
  * Get size of memory used by comm point.
  * For TCP handlers this includes subhandlers.