in reply to exec creating zombie processes
I must be missing something. Why can’t you put another waitpid() call in your code, after the kill?
Yes, that does mean that, after firing the fatal bullet, your code must wait for the flailing corpse to actually hit the ground, but ...
As you well know, Unix systems are designed to keep dead children in this “zombie” state so that you can gather their final-status by doing a waitpid. You do this in one case but not the other. If an exception or signal is not thrown, you reap the (dead) child correctly. But if one is, your one waitpid call is never executed and you do not execute another one in your exception-handling block. I think that is the crux of your problem.