]> git.ipfire.org Git - thirdparty/mtr.git/commitdiff
fix(dns): terminate resolver subprocesses on exit
authorDarafei Praliaskouski <me@komzpa.net>
Thu, 7 May 2026 21:45:35 +0000 (01:45 +0400)
committerDarafei Praliaskouski <me@komzpa.net>
Thu, 7 May 2026 21:45:35 +0000 (01:45 +0400)
ui/dns.c
ui/dns.h
ui/mtr.c

index 824b401136b77a1ae3211fdcf4941e06c7a3bee4..aac3e78d0d45e1f1f220b3ae9dc06951ddeea9d7 100644 (file)
--- a/ui/dns.c
+++ b/ui/dns.c
@@ -36,6 +36,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
+#include <sys/wait.h>
 
 #include "mtr.h"
 #include "dns.h"
@@ -71,8 +72,10 @@ char *strlongip(
 #define UNUSED_IF_NO_IPV6 ATTRIBUTE_UNUSED
 #endif
 
-static int todns[2], fromdns[2];
+static int todns[2] = { -1, -1 };
+static int fromdns[2] = { -1, -1 };
 static FILE *fromdnsfp;
+static pid_t dns_pid;
 
 static int longipstr(
     char *s,
@@ -133,6 +136,10 @@ void dns_open(
         int i;
         FILE *infp;
 
+        if (setpgid(0, 0) < 0) {
+            error(EXIT_FAILURE, errno, "can't create DNS process group");
+        }
+
         /* Automatically reap children. */
         if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
             error(EXIT_FAILURE, errno, "signal");
@@ -186,6 +193,10 @@ void dns_open(
         int flags;
 
         /* the parent. */
+        if (setpgid(pid, pid) < 0 && errno != EACCES) {
+            error(0, errno, "can't set DNS process group");
+        }
+        dns_pid = pid;
         close(todns[0]);        /* close the pipe ends we don't need. */
         close(fromdns[1]);
         fromdnsfp = fdopen(fromdns[0], "r");
@@ -195,6 +206,44 @@ void dns_open(
     }
 }
 
+void dns_close(
+    void)
+{
+    int status;
+
+    if (todns[1] >= 0) {
+        close(todns[1]);
+        todns[1] = -1;
+    }
+    if (fromdnsfp) {
+        fclose(fromdnsfp);
+        fromdnsfp = NULL;
+        fromdns[0] = -1;
+    } else if (fromdns[0] >= 0) {
+        close(fromdns[0]);
+        fromdns[0] = -1;
+    }
+
+    if (dns_pid <= 0) {
+        return;
+    }
+
+    if (kill(-dns_pid, SIGTERM) < 0 && errno != ESRCH) {
+        error(0, errno, "kill DNS process group");
+    }
+
+    while (waitpid(dns_pid, &status, 0) < 0) {
+        if (errno != EINTR) {
+            if (errno != ECHILD) {
+                error(0, errno, "wait DNS process");
+            }
+            break;
+        }
+    }
+
+    dns_pid = 0;
+}
+
 int dns_waitfd(
     void)
 {
index 52ce1b7bcedc1a23d45e7aba22c70a78d950bd85..c885f4d2e4656c14071bfa80cbbbfb9f7f5258cc 100644 (file)
--- a/ui/dns.h
+++ b/ui/dns.h
@@ -24,6 +24,8 @@
 
 extern void dns_open(
     void);
+extern void dns_close(
+    void);
 extern int dns_waitfd(
     void);
 extern void dns_ack(
index 6886bce346c52adb60868055f9331c567dcf4e14..513cf39b261d3b50633830c240f243cc4f08404e 100644 (file)
--- a/ui/mtr.c
+++ b/ui/mtr.c
@@ -866,6 +866,7 @@ int main(
 
         net_end_transit();
         display_close(&ctl);
+        dns_close();
         unlock(stdout);
 
         if (ctl.Interactive)