The root problem, which is extremely difficult to deal with, is basically a race-condition: the parent might “determine” the status of a child, but, before it can react to the status that it has thusly determined, the status of the child has changed. Strictly speaking, you don’t even know that your list-of-children is instantaneously correct.
Obviously, the most desirable thing to do would be to schlep the entire responsibility off to an existing known-good CPAN module, such as, say, Parallel::ForkManager. Can you find a way to do that?
Otherwise, I suggest that you should devise that the only role of the parent process/thread should be “to run the nursery.” All of the other responsibilities, including checking whether a particular condition has occurred, ought to be the responsibilities of children. If that special child informs you that, indeed, “ka-ka has occurred,” the parent should respond by issuing a signal to every one of its children that asks them to “please die, as soon as you possibly can,” then waits for them all to do so. It does not poll them to see if they are alive: it does not have to. If at all possible, it also does not kill them. (How messy ... and, how unpredictable. Each child, once alive, is responsible for setting its own affairs in order upon the occasion of its own death... timely or otherwise.)
I have consistently found (and, maybe it’s just me ...) that if you try to give the parent process many responsibilities of its own to take care of in addition to “watching the kids,” the kids get into trouble in ways that you could not possibly have anticipated and could never reproduce. (This being a case in which computers imitate real life!!)