I'm using golang to call pppd and then kill it after a while. However I got a lot of defunct proccesses in this way.
This is how I run pppd
exec.Command("sh", "-c", "pppd call vpn").CombinedOutput()
This is how I kill it.
exec.Command("sh", "-c", "pkill pppd").CombinedOutput()
Then I got a lot of this
root 31541 23536 0 10:54 ? 00:00:00 [pppd] <defunct>
root 31929 23356 0 10:55 ? 00:00:00 [pptpgw] <defunct>
root 31933 23356 0 10:55 ? 00:00:00 [pptpcm] <defunct>
root 31940 23356 0 10:55 ? 00:00:00 [pppd] <defunct>
root 31993 23536 0 10:55 ? 00:00:00 [pptpgw] <defunct>
root 31997 23536 0 10:55 ? 00:00:00 [pptpcm] <defunct>
root 31998 23536 0 10:55 ? 00:00:00 [pppd] <defunct>
root 32012 23356 0 10:55 ? 00:00:00 [pptpgw] <defunct>
root 32016 23356 0 10:55 ? 00:00:00 [pptpcm] <defunct>
root 32017 23356 0 10:56 ? 00:00:00 [pppd] <defunct>
root 32070 23536 0 10:56 ? 00:00:00 [pptpgw] <defunct>
root 32074 23536 0 10:56 ? 00:00:00 [pptpcm] <defunct>
root 32075 23536 0 10:56 ? 00:00:00 [pppd] <defunct>
root 32083 23356 0 10:56 ? 00:00:00 [pptpgw] <defunct>
root 32087 23356 0 10:56 ? 00:00:00 [pptpcm] <defunct>
root 32089 23356 0 10:56 ? 00:00:00 [pppd] <defunct>
root 32131 23536 0 10:57 ? 00:00:00 [pptpgw] <defunct>
root 32135 23536 0 10:57 ? 00:00:00 [pptpcm] <defunct>
root 32148 23536 0 10:57 ? 00:00:00 [pppd] <defunct>
root 32160 23356 0 10:57 ? 00:00:00 [pptpgw] <defunct>
root 32164 23356 0 10:57 ? 00:00:00 [pptpcm] <defunct>
root 32165 23356 0 10:57 ? 00:00:00 [pppd] <defunct>
root 32177 23536 0 10:57 ? 00:00:00 [pptpgw] <defunct>
root 32181 23536 0 10:57 ? 00:00:00 [pptpcm] <defunct>
How can I avoid defunct processes.
These "zombie" processes are created when a process has finished, but the parent has not read their exit status via the wait
system call.
I would guess that all you need to do is call (*Cmd).Wait()
on every command structure you create. Obviously This will be less straight forward than you may like, since you probably don't want to call Wait
on the first command until after the second command is finished.
EDIT: As is pointed out in the comments, (*Cmd).CombinedOutput()
calls (*Cmd).Run()
, which calls (*Cmd).Wait()
... So the above is wrong. The real answer in this case is that for some reason sh
isn't cleaning up, and so the solution is to cut out the midle man and do the call like so:
exec.Command("pppd", "call", "vpn").CombinedOutput()
That'll teach me to read the docs a little closer next time...