[Dnsmasq-discuss] Leftover helper process after main process exit on FreeBSD
Roman Bogorodskiy
bogorodskiy at gmail.com
Fri Jun 13 12:30:47 UTC 2025
Hi,
I've noticed an issue on FreeBSD which I can reproduce this way:
# ./src/dnsmasq --interface=bridge0 --except-interface=lo0 --dhcp-range=192.168.127.2,192.168.127.254,255.255.255.0 --dhcp-script=/usr/bin/true
$ ps aux|grep dnsm
nobody 12741 0,0 0,0 14500 3128 - I 13:43 0:00,00 ./src/dnsmasq --interface=bridge0 --except-interface=lo0 --dhcp-range=192.168.127.2,192.168.127.254,255.255.255.0 --dhcp-script=/usr/bin/true
root 12742 0,0 0,0 14500 3008 - I 13:43 0:00,00 ./src/dnsmasq --interface=bridge0 --except-interface=lo0 --dhcp-range=192.168.127.2,192.168.127.254,255.255.255.0 --dhcp-script=/usr/bin/true
novel 12763 0,0 0,0 14192 2588 1 S+ 13:44 0:00,00 grep dnsm
$
# kill 12741
$ ps aux|grep dns
root 12742 0,0 0,0 14500 3008 - I 13:43 0:00,00 ./src/dnsmasq --interface=bridge0 --except-interface=lo0 --dhcp-range=192.168.127.2,192.168.127.254,255.255.255.0 --dhcp-script=/usr/bin/true
novel 12785 0,0 0,0 14192 2560 1 S+ 13:45 0:00,00 grep dns
$
There is a leftover process. When I attach to it using gdb I see:
(gdb) attach 12742
Attaching to program: /usr/home/novel/code/dnsmasq/src/dnsmasq, process 12742
Reading symbols from /lib/libc.so.7...
Reading symbols from /usr/lib/debug//lib/libc.so.7.debug...
Reading symbols from /lib/libsys.so.7...
Reading symbols from /usr/lib/debug//lib/libsys.so.7.debug...
Reading symbols from /libexec/ld-elf.so.1...
Reading symbols from /usr/lib/debug//libexec/ld-elf.so.1.debug...
_read () at _read.S:4
4 PSEUDO(read)
(gdb) bt
#0 _read () at _read.S:4
#1 0x00000000002208a1 in read_write (fd=19, packet=0x8204deea8 "\260\236\212\"\b", size=112, rw=1) at util.c:783
#2 0x000000000024e6ca in create_helper (event_fd=16, err_fd=18, uid=0, gid=0, max_fd=1877346) at helper.c:199
#3 0x000000000023b1f1 in main (argc=5, argv=0x8204df170) at dnsmasq.c:743
(gdb)
So it looks like it's stuck reading from pipefd[0]:
(gdb) fr 2
#2 0x000000000024e6ca in create_helper (event_fd=16, err_fd=18, uid=0, gid=0, max_fd=1877346) at helper.c:199
199 if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), RW_READ))
(gdb)
It also looks like both fd's are open in the helper side:
(gdb) p pipefd
$12 = {19, 20}
(gdb)
(gdb) call fcntl(20, 1)
$13 = 0
(gdb)
Now if I close(20):
(gdb) call close(20)
$14 = 0
(gdb) c
Continuing.
[Inferior 1 (process 12742) exited normally]
(gdb)
So the following change fixed this for me:
--- a/src/helper.c
+++ b/src/helper.c
@@ -96,6 +96,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
close(pipefd[0]); /* close reader side */
return pipefd[1];
}
+ else
+ close(pipefd[1]);
/* ignore SIGTERM and SIGINT, so that we can clean up when the main process gets hit
and SIGALRM so that we can use sleep() */
FWIW, that's happening on FreeBSD 15.0-CURRENT amd64 and latest master
of dnsmasq.
However, I'm not sure that these reproduction steps are 100% sufficient.
I wasn't able to reproduce that on another FreeBSD 14.2-RELEASE amd64
system with Dnsmasq version 2.91.
Thanks,
Roman
More information about the Dnsmasq-discuss
mailing list