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?

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
kanoz
  • 151
  • 1
  • 1
  • 4
  • 2
    What are you trying to achieve ? – cnicutar Aug 24 '11 at 07:13
  • Allow mixing of background and foreground processes by writing and installing a proper signal handler function – kanoz Aug 24 '11 at 07:18
  • 1
    What should the signal handler do ? – cnicutar Aug 24 '11 at 07:19
  • kills or ignores zombies – kanoz Aug 24 '11 at 07:20
  • 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. – Jonathan Leffler Aug 24 '11 at 07:21
  • 3
    This seems to be related to [Example of `waitpid()`, `WNOHANG`, and `SIGCHLD`](http://stackoverflow.com/questions/7155810/example-of-waitpid-wnohang-and-sigchld). – Jonathan Leffler Aug 24 '11 at 07:25

1 Answers1

35

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. */
edwardw
  • 12,652
  • 3
  • 40
  • 51
cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • 2
    where should i call this method? – kanoz Aug 24 '11 at 07:25
  • @kanoz Read the last paragraph :-) – cnicutar Aug 24 '11 at 07:26
  • 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. – hfingler Sep 01 '11 at 03:38
  • @polar Somewhere before starting to fork. – cnicutar Sep 01 '11 at 07:55
  • 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? – kapilddit Apr 14 '14 at 13:56
  • @kapilddit 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 ? – cnicutar Apr 14 '14 at 14:05
  • 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 ? – kapilddit Apr 14 '14 at 14:21
  • If using Linux you can look in `/proc/[pid]/status` and see the mask `SigIgn`. – cnicutar Apr 14 '14 at 14:28
  • 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. – kapilddit Apr 14 '14 at 14:33
  • 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. – Patrick Chkoreff Apr 17 '23 at 18:56