While working on my project geoip-shell, I noticed the following weirdness.
For a simplified example, I create a script at /usr/bin/ttt.sh with following contents:
#!/bin/sh
/bin/sh /usr/bin/ttt2.sh
I create a script at /usr/bin/ttt2.sh with following contents:
#!/bin/sh
sleep 3 &
wait $!
Then I add the following section to /etc/config/firewall:
config include 'ttt'
option enabled '1'
option type 'script'
option path '/usr/bin/ttt.sh'
Essentially, the firewall include script /usr/bin/ttt.sh calls another script /usr/bin/ttt2.sh, which forks sleep and waits on the forked process to finish.
Then I issue the command
service firewall restart
This command never finishes. The reason: the spawned sleep process becomes a zombie:
root@OpenWrt:~# ps | grep sleep | grep -v grep
2929 root 0 Z [sleep]
If either script is run directrly, sleep does not become a zombie and the process exits as expected.
So something about how the firewall include script is executed is different and I'm not sure what. Is there a workaround?
(the reason I want to call sleep with &, i.e. fork it and then use wait is that when executing sleep, the script ttt2.sh ignores kill commands, and when executing wait, it doesn't ignore them. and I want the script to respond to kill commands.)
P.s. this is the command line of the call (issued by firewall4):
8641 root 1184 S sh -c exec 1000>&-; config() { echo "You cannot use UCI in firewall includes!" >&2; exit 1; }; . '/usr/bin/ttt.sh'
Issuing this command manually doesn't spawn a zombie either:
sh -c exec 1000>&-; config() { echo "You cannot use UCI in firewall includes!" >&2; exit 1; }; . '/usr/bin/ttt.sh'