]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Fix a crash when dig or host receive a signal
authorTony Finch <fanf@isc.org>
Thu, 30 Mar 2023 16:56:08 +0000 (17:56 +0100)
committerTony Finch <fanf@isc.org>
Fri, 31 Mar 2023 09:52:54 +0000 (09:52 +0000)
When the loopmanager is shutting down following a signal,
`dig` and `host` should stop cleanly. Before this commit
they were oblivious to ISC_R_SHUTTINGDOWN.

The `isc_signal` callbacks now report this kind of mistake
with a stack backtrace.

CHANGES
bin/dig/dighost.c
lib/isc/loop_p.h
lib/isc/signal.c

diff --git a/CHANGES b/CHANGES
index 211adb7403b4a86df37f27e22e6d6355cca67af7..3a35753cdb072b2af1e04ab01823a6de5b742d58 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,6 @@
+6134.  [bug]           Fix a crash when dig or host receive a signal.
+                       [GL #3970]
+
 6133.  [cleanup]       Refactor the isc_job_run() to not make any allocations
                        by embedding isc_job_t into callback argument, and
                        running it directly.  As a side-effect, isc_async_run
index 97b53f1b2fa2cc7aa016f2bec3b3c506aa28ed0d..e36023e2989c00dc54ee5706844e095dac50e405 100644 (file)
@@ -3911,7 +3911,9 @@ recv_done(isc_nmhandle_t *handle, isc_result_t eresult, isc_region_t *region,
 
        lookup_attach(query->lookup, &l);
 
-       if (eresult == ISC_R_CANCELED || query->canceled) {
+       if (eresult == ISC_R_CANCELED || eresult == ISC_R_SHUTTINGDOWN ||
+           query->canceled)
+       {
                debug("recv_done: cancel");
                isc_nmhandle_detach(&query->readhandle);
                if (!query->canceled) {
index 8810a36619776729443d6779a4535bde5c61b5e1..9594a0f306a377e95351fa9b935c9d43327bfcff 100644 (file)
@@ -121,7 +121,11 @@ struct isc_loopmgr {
 /*
  * Signal Handler
  */
+#define SIGNAL_MAGIC   ISC_MAGIC('S', 'I', 'G', ' ')
+#define VALID_SIGNAL(t) ISC_MAGIC_VALID(t, SIGNAL_MAGIC)
+
 struct isc_signal {
+       int magic;
        uv_signal_t signal;
        isc_loop_t *loop;
        isc_signal_cb cb;
index 69c7541288999b9b1a1e72661d56ab95b433b79b..5181f15af180d50e5aa5863701bd75590961c043 100644 (file)
@@ -30,6 +30,7 @@ isc_signal_new(isc_loopmgr_t *loopmgr, isc_signal_cb cb, void *cbarg,
 
        signal = isc_mem_get(isc_loop_getmctx(loop), sizeof(*signal));
        *signal = (isc_signal_t){
+               .magic = SIGNAL_MAGIC,
                .cb = cb,
                .cbarg = cbarg,
                .signum = signum,
@@ -48,18 +49,22 @@ isc_signal_new(isc_loopmgr_t *loopmgr, isc_signal_cb cb, void *cbarg,
 static void
 isc__signal_destroy_cb(uv_handle_t *handle) {
        isc_signal_t *signal = uv_handle_get_data(handle);
-       isc_loop_t *loop = signal->loop;
+       isc_loop_t *loop = NULL;
 
-       isc_mem_put(loop->mctx, signal, sizeof(*signal));
+       REQUIRE(VALID_SIGNAL(signal));
 
+       loop = signal->loop;
+       isc_mem_put(loop->mctx, signal, sizeof(*signal));
        isc_loop_detach(&loop);
 }
 
 void
 isc_signal_destroy(isc_signal_t **signalp) {
-       isc_signal_t *signal;
+       isc_signal_t *signal = NULL;
+
+       REQUIRE(signalp != NULL);
+       REQUIRE(VALID_SIGNAL(*signalp));
 
-       REQUIRE(signalp != NULL && *signalp != NULL);
        signal = *signalp;
        *signalp = NULL;
 
@@ -68,7 +73,10 @@ isc_signal_destroy(isc_signal_t **signalp) {
 
 void
 isc_signal_stop(isc_signal_t *signal) {
-       int r = uv_signal_stop(&signal->signal);
+       int r;
+
+       REQUIRE(VALID_SIGNAL(signal));
+       r = uv_signal_stop(&signal->signal);
        UV_RUNTIME_CHECK(uv_signal_stop, r);
 }
 
@@ -76,6 +84,7 @@ static void
 isc__signal_cb(uv_signal_t *handle, int signum) {
        isc_signal_t *signal = uv_handle_get_data((uv_handle_t *)handle);
 
+       REQUIRE(VALID_SIGNAL(signal));
        REQUIRE(signum == signal->signum);
 
        signal->cb(signal->cbarg, signum);
@@ -83,7 +92,9 @@ isc__signal_cb(uv_signal_t *handle, int signum) {
 
 void
 isc_signal_start(isc_signal_t *signal) {
-       int r = uv_signal_start(&signal->signal, isc__signal_cb,
-                               signal->signum);
+       int r;
+
+       REQUIRE(VALID_SIGNAL(signal));
+       r = uv_signal_start(&signal->signal, isc__signal_cb, signal->signum);
        UV_RUNTIME_CHECK(uv_signal_start, r);
 }