Skip to content
Advertisement

Creating “background running” children with fork() and kill each of them with signals

I need to create n children from the same parent, and have them running while the parent asks infinitely for a signal to send to some child. I made the parent create those n children, but they finished executing, so I made them enter a while(1) loop. The problem is, when I try to kill any child, it becomes a zombie process instead of actually terminating its execution. I’m guessing that’s because the parent is still waiting for the children to terminate execution and they don’t send the exit status. So… First of all, do I really need to make the children enter an infinite while loop to make them be running while the parent is asking for the signals? If I do, how do I avoid this “never terminating execution” problem? I need to find a way for the children to exit that while loop and send the actual “finished execution” signal since I think I can’t use wait() because the children never actually finish running, they are just terminated by the parent.

Thanks. PS: Running in Linux. This is my code

int main(){
    int i;
    pid_t parent = getpid();
    pid_t pid[4];
    printf("parent with pid %dn", parent);

    for(i = 0; i < 5; i++){
        pid[i] = fork();
        if(pid[i] < 0){
            perror("Error in fork.");
            exit(1);
        } else if(pid[i] == 0 && getppid() == padre) {
            printf("Number: %d   pid %d, parent: %dn", i, getpid(), getppid());
            while(1);
        }
    }

    if(getpid() == padre){
        while(1){
            printf("Enter pid and signal:n");
            int x, y;
            scanf("%d", &x); // pid
            scanf("%d", &y); // signal
            printf("you did: kill(%d, %d)n", x, y);
            kill(x, y);
        }
    }
    return 0;
}

EDIT: Final code with answer implemented: https://github.com/sebasura/sistope

Advertisement

Answer

The problem is, when I try to kill any child, it becomes a zombie process instead of actually terminating its execution.

Well, yes and no. Becoming a zombie is normally what happens when a process terminates, until that process is collected by its parent. A zombie takes up a bit of space in the process table, but it is not running, and therefore consumes no CPU.

I’m guessing that’s because the parent is still waiting for the children to terminate execution and they don’t send the exit status.

No, it’s because kill() just sends a signal. You need to use one of the wait() functions — perhaps waitpid() — to actually collect the terminated child.

So… First of all, do I really need to make the children enter an infinite while loop to make them be running while the parent is asking for the signals?

No. The child can use sigwait() or one of its variants to wait for a signal from a designated set, or pause() to suspend execution pending receipt of any signal that terminates the process or triggers a signal handler function. Note, however, that there are some signals that by default do neither of those, so sigwait() is probably the better alternative.

If I do, how do I avoid this “never terminating execution” problem?

The child must terminate as a result of receiving the signal. That’s already happening for you, because the children are becoming zombies. With your present code it may depend on which signal you send, however, for there are some whose default handling does not terminate the process.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement