]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Run isc__nm_http_stoplistening() synchronously in netmgr
authorOndřej Surý <ondrej@sury.org>
Thu, 6 May 2021 07:03:33 +0000 (09:03 +0200)
committerEvan Hunt <each@isc.org>
Fri, 7 May 2021 21:28:32 +0000 (14:28 -0700)
When isc__nm_http_stoplistening() is run from inside the netmgr, we need
to make sure it's run synchronously.  This commit is just a band-aid
though, as the desired behvaior for isc_nm_stoplistening() is not always
the same:

  1. When run from outside user of the interface, the call must be
     synchronous, e.g. the calling code expects the call to really stop
     listening on the interfaces.

  2. But if there's a call from listen<proto> when listening fails,
     that needs to be scheduled to run asynchronously, because
     isc_nm_listen<proto> is being run in a paused (interlocked)
     netmgr thread and we could get stuck.

The proper solution would be to make isc_nm_stoplistening()
behave like uv_close(), i.e., to have a proper callback.

lib/isc/netmgr/http.c
lib/isc/netmgr/tlsstream.c

index 4482e2023d5964c8686973479097e9b45f5726cc..021feaa3c3b838a44edd228b3bf1c50e925dcdd9 100644 (file)
@@ -2239,8 +2239,6 @@ isc_nm_http_endpoint(isc_nmsocket_t *sock, const char *uri, isc_nm_recv_cb_t cb,
 
 void
 isc__nm_http_stoplistening(isc_nmsocket_t *sock) {
-       isc__netievent_httpstop_t *ievent = NULL;
-
        REQUIRE(VALID_NMSOCK(sock));
        REQUIRE(sock->type == isc_nm_httplistener);
 
@@ -2250,9 +2248,15 @@ isc__nm_http_stoplistening(isc_nmsocket_t *sock) {
                ISC_UNREACHABLE();
        }
 
-       ievent = isc__nm_get_netievent_httpstop(sock->mgr, sock);
-       isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
-                              (isc__netievent_t *)ievent);
+       if (!isc__nm_in_netthread()) {
+               isc__netievent_httpstop_t *ievent =
+                       isc__nm_get_netievent_httpstop(sock->mgr, sock);
+               isc__nm_enqueue_ievent(&sock->mgr->workers[sock->tid],
+                                      (isc__netievent_t *)ievent);
+       } else {
+               isc__netievent_httpstop_t ievent = { .sock = sock };
+               isc__nm_async_httpstop(NULL, (isc__netievent_t *)&ievent);
+       }
 }
 
 static void
@@ -2294,7 +2298,6 @@ isc__nm_async_httpstop(isc__networker_t *worker, isc__netievent_t *ev0) {
        UNUSED(worker);
 
        REQUIRE(VALID_NMSOCK(sock));
-       REQUIRE(sock->tid == isc_nm_tid());
 
        atomic_store(&sock->listening, false);
        atomic_store(&sock->closing, false);
index 264ffcde41ece416c92949906fd023a1d60f9c69..fab2072f22201564a501a0a999e4625e5736503a 100644 (file)
@@ -849,6 +849,12 @@ isc__nm_tls_stoplistening(isc_nmsocket_t *sock) {
        REQUIRE(VALID_NMSOCK(sock));
        REQUIRE(sock->type == isc_nm_tlslistener);
 
+       if (!atomic_compare_exchange_strong(&sock->closing, &(bool){ false },
+                                           true)) {
+               INSIST(0);
+               ISC_UNREACHABLE();
+       }
+
        atomic_store(&sock->listening, false);
        atomic_store(&sock->closed, true);
        sock->recv_cb = NULL;