Xrouter平台运行过程中,出现很多dnsmasq的僵尸进程:
# ps w
191 root 0:00 udhcpc -i eth0 -p /run/net/udhcpc.eth0.pid -s /lib/network
192 nobody 0:00 dnsmasq -k -C /etc/dnsmasq.conf -C /run/net/dnsmasq.conf -
196 root 0:17 hostapd -i ap2g /run/net/hostapd-ap2g.conf
202 root 0:26 hostapd -i ap5g /run/net/hostapd-ap5g.conf
208 root 0:00 udhcpc6 -i eth0 -p /run/net/udhcpc6.eth0.pid -s /lib/netwo
234 nobody 0:00 [dnsmasq]
235 nobody 0:00 [dnsmasq]
236 nobody 0:00 [dnsmasq]
239 nobody 0:00 [dnsmasq]
240 nobody 0:00 [dnsmasq]
241 nobody 0:00 [dnsmasq]
242 nobody 0:00 [dnsmasq]
243 nobody 0:00 [dnsmasq]
244 nobody 0:00 [dnsmasq]
245 nobody 0:00 [dnsmasq]
246 nobody 0:00 [dnsmasq]
247 nobody 0:00 [dnsmasq]
248 nobody 0:00 [dnsmasq]
使用procmon工具查看,确实是dnsmasq fork出来的。查看dnsmasq的源码,发现是注册SIGCHLD信号处理函数,在信号处理函数中,给主进程写事件,主进程收到事件后,使用waitpid回收。
经过一番分析后,发现SIGCHLD被block了:
# cat /proc/192/status
SigPnd: 0000000000000000
ShdPnd: 0000000000010000
SigBlk: 0000000000010000
SigIgn: 0000000000001000
SigCgt: 0000000000016a03
可以看到SigBlk,17号信号被block了。
$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS
继续追踪发现,是event库使用signalfd接收sigchld事件,主动把sigchld给block了。dnsmasq从父亲继承了这个block。
修改如下:
diff --git a/app/platform/libbase/event.c b/app/platform/libbase/event.c
index 0587dce..6e536d9 100644
--- a/app/platform/libbase/event.c
+++ b/app/platform/libbase/event.c
@@ -28,7 +28,10 @@ static int create_signalfd()
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGCHLD);
- sigprocmask(SIG_BLOCK, &sigmask, NULL);
+
+ // don't block SIGCHLD
+ // or child process may not wait child (zoombie proc)
+ // sigprocmask(SIG_BLOCK, &sigmask, NULL);
return signalfd(-1, &sigmask, SFD_NONBLOCK);
}
参考
https://access.redhat.com/solutions/3478631