> You aren't allowed to do very much between vfork() and exec().
> Basically just sort out the child's fd table.
> And I suspect that needs to only look at on-stack data.
> 
> Having the child execute first is only an optimisation.
> The child can fault on paged-out memory (even its stack) which
> would allow the parent to run.

Yes. Definitely!  :)
And per man page 'On some implementations, vfork() is equivalent to fork().'
race conditions between parent and children is possible too, 
depends on implementation.
https://linux.die.net/man/3/vfork
https://man7.org/linux/man-pages/man2/vfork.2.html

A possible approach is: let crond parent prepare the DGRAM socket fd 
connecting to /dev/log, avoid been delayed connecting until the first 
message is logged by vfork() children.

This patch add LOG_NDELAY to openlog(), let parent open the DGRAM socket 
connecting to '/dev/log' immediately (if success). 
Upcoming vfork() children would get the same static var 'LogFile', just 
using it and not modifying it, because it is all setup ready by parent.

For example,
after applied this patch, crond parent pid=23384 will prepared the DGRAM 
socket fd connecting to '/dev/log', then vfork() children.

# grep -rE "^vfork|^sock.*DGRAM" 20231208_05.log.23384
socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="/dev/log"}, 110) = 0
vfork()                                 = 28336
vfork()                                 = 2392
vfork()                                 = 6124
... <cut too long dummy> ...

And vfork() children would just use fd=3 for logging.

# grep -rE "^vfork|^sock.*DGRAM|connect.*log|sendto" 20231208_05.log.28336
sendto(3, "<75>Dec  8 15:38:01 crond[28336]: can't change directory to 
'/share/ho"..., 81, MSG_NOSIGNAL, NULL, 0) = 81
# grep -rE "^vfork|^sock.*DGRAM|connect.*log|sendto" 20231208_05.log.2392
sendto(3, "<75>Dec  8 15:39:00 crond[2392]: can't change directory to 
'/share/hom"..., 80, MSG_NOSIGNAL, NULL, 0) = 80
# grep -rE "^vfork|^sock.*DGRAM|connect.*log|sendto" 20231208_05.log.6124
sendto(3, "<75>Dec  8 15:40:00 crond[6124]: can't change directory to 
'/share/hom"..., 80, MSG_NOSIGNAL, NULL, 0) = 80

Note that '/dev/log' should be ready by syslogd or syslog-ng before crond.

After poking around the mailing list found an old thread: inetd fd leak?
http://lists.busybox.net/pipermail/busybox/2009-September/070195.html
https://git.busybox.net/busybox/commit/?id=cfc216345e18081cba9ac3ed0464abf5d7f40cea
It looks like inetd has a similar case in old days, 
and the solution is add LOG_NDELAY into openlog().

Hope this patch could be applied into git :)

--

Regards,
Jones Syue | 薛懷宗
QNAP Systems, Inc.
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to