How can I handle SIGCHLD?
Asked Answered
D

1

15

I need to handle SIGCHLD properly. How can I use it with my existing code? at the moment I cant wait for the child process unless I use 0 instead of WNOHANG|WUNTRACED.

status = 0; 
pid_t child, endID;

if(amp == 1)
        signal( SIGCHLD, SIG_IGN ); 

child = fork(); 

if (child  <  0) {    
        perror("fork() error\n");
        exit(EXIT_FAILURE);

} else if (child == 0) { 
        // do sth here
        perror("error\n");

} else { 
        //sleep(1)

If I remove sleep then parent is executed 1st.. why?

Dedicate answered 24/8, 2011 at 7:11 Comment(6)
What are you trying to achieve ?Birdsong
Allow mixing of background and foreground processes by writing and installing a proper signal handler functionDedicate
What should the signal handler do ?Birdsong
kills or ignores zombiesDedicate
As written, you will likely have waitpid() return immediately because (a) the child has not died and (b) you said 'do not wait for the child to die'. You would normally wrap the waitpid() in a loop. Also, it is not clear why you're waiting for vars->pid when the child pid is only available in child. It seems a little odd that you pass vars->status rather than &vars->status or &status. The variables status and endID are unused.Butylene
This seems to be related to Example of waitpid(), WNOHANG, and SIGCHLD.Butylene
B
36

Here is a start (but read below):

static void
child_handler(int sig)
{
    pid_t pid;
    int status;

    /* EEEEXTEERMINAAATE! */
    while((pid = waitpid(-1, &status, WNOHANG)) > 0)
        ;
}

/* Establish handler. */
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = child_handler;

sigaction(SIGCHLD, &sa, NULL);

Of course, this is all pointless. If the parent simply ignores SIGCHLD, the children are silently reaped and won't turn into zombies.

Quoting TLPI:

Explicitly setting the disposition of SIGCHLD to SIG_IGN causes any child process that subsequently terminates to be immediately removed from the system instead of being converted into a zombie.

So something like this should do the trick for you:

signal(SIGCHLD, SIG_IGN); /* Silently (and portably) reap children. */
Birdsong answered 24/8, 2011 at 7:22 Comment(10)
where should i call this method?Dedicate
@Dedicate Read the last paragraph :-)Birdsong
Just came across this question because i needed to handle SIGCHLD, and i didn't find it very clear on where the line you gave us should be called. As it doesn't need any pid or anything i just put it anywhere, is it right? Thanks @cnicutar.Teador
@polar Somewhere before starting to fork.Birdsong
As you said: Explicitly setting the disposition of SIGCHLD to SIG_IGN causes any child process that subsequently terminates to be immediately removed from the system instead of being converted into a zombie. How can check & prevent this situation? I think this thing is happening in my case?Addie
@Addie I don't understand the question completely. Do you want to prevent the children from being reaped automatically ? Do you want to know if you process sets the disposition to SIG_IGN ?Birdsong
Yes, your understanding is correct. I want my process to be converted to zombie. So I can read the status of child. currently I am getting -1 from waitpid with errno ECHILD. I want to know my process sets the disposition to SIG_IGN ?Addie
If using Linux you can look in /proc/[pid]/status and see the mask SigIgn.Birdsong
I am not able to see any pid for child process in /proc/pid/status. Do I need to write signal handler? I don't want to kill or ignore zombie child process. I want child pid as return value from waitpid.Addie
The explicit child_handler approach is not entirely pointless. It has the virtue of making it so that SIGCHLD interrupts system calls such as read. That can prevent a parent process from blocking forever on read.Hecto

© 2022 - 2024 — McMap. All rights reserved.