Solved

signal handler for SIGCHLD gets called twice if parent process also gets killed

Posted on 2003-10-23
17
991 Views
Last Modified: 2013-12-26
Hi,

I have a parent process that forks a child process and from there execlp another executable. The parent process and the exe uses pipes for IPC. The parent process has a signal handler that handles the SIGCHLD signal as follows :

    struct sigaction act;

    act.sa_handler = SIG_IGN;
    sigemptyset(&act.sa_mask);
    act.sa_flags   = 0;
    sigaction(SIGPIPE, &act, 0);

    act.sa_handler = child_killed; //handler function
    act.sa_flags  = SA_NOCLDSTOP | SA_NODEFER;
    sigemptyset(&act.sa_mask);

    if(sigaction(SIGCHLD,&act,0)) {
        exit(1);
    }

In the child_killed(), I close the read end of the pipe.
Some times just after the child process exits, the parent process goes 100% (at times I see that the signal handler gets called in logs and some times i do not see the logs, so i cannot be sure that everytime the problem happens the signal handler gets called in parent). Also the child process becomes a Zombie. After I kill and restart the Parent process I see in its logs that the signal handler is called again but this time with child pid as -1.  

Can you please tell me why the signal handler is getting called in the newly started parent process.

Also I would like to know that whether there is a chance that even after the child exits the signal handler doesn't gets called in the parent.

Thanks,
Avinash
0
Comment
Question by:avidamani
  • 8
  • 5
  • 2
  • +2
17 Comments
 
LVL 45

Expert Comment

by:sunnycoder
Comment Utility
>Can you please tell me why the signal handler is getting called in the newly started parent process.
cannot be unless there is a bug in the library ... run your program through a debugger

>whether there is a chance that even after the child exits the signal handler doesn't gets called in the parent.
yes, if you are executing child_killed() when a child exits, signal will not be delivered ... this is the default behaviour... when you are handling a signal and same signal arrives, it is not delivered ... also if more than one children exit simultaneously, your application will see only one signal
you might like to look into sigpending()
0
 

Author Comment

by:avidamani
Comment Utility
Hi sunnycoder,

Thanks for the reply. Can you elaborate which library are you talking about.

Also there is only one child process, so there is no chance of getting another sigchild. THe problem is that the parent process goes upto 100% CPU utilization around the time the child exits. There is no way to confirm whether the parent went 100% before the sigchld came or after that. Also the problem is happening rarely and so there is no way to reproduce it with the code as it is.
1 more thing, is it possible to miss a signal if theparent process is very busy processing something else.
Cause i know for sure that if i do not close the reading end of the pipe after the child exits, parent process will shoot upto 100% quickly, but whats baffling me is that why the sigchld handler is not getting called.

Thanks,
Avinash

0
 

Author Comment

by:avidamani
Comment Utility
Also to add, The parent and child process are communicating through pipe, where Child is the writer and parent reads from the pipe using the following :

       XtAddInput(fd, (char *)xmask, callback, ptr));

Now if the child exits/gets killed, what will the status of the pipe at parent, will the callback keep on getting called? SIGPIPE signal comes when you write to a pipe which has no reader. right? Is there anything that tells that the pipe is empty from which you are reading, i.e. there is no writer to it.

Thanks,
Avinash
0
 
LVL 1

Expert Comment

by:fsign21
Comment Utility
Could you please post a bit more of you code
1) where do you call pipe() and fork()
2) more important, where and how do you call wait() or waitpid(). Since, you are getting zombies, I assume, it is something wrong with waiting.
If the parent doesn't wait, but exits before the child process does, then the child is adopted by another process (usually the one with PID 1). After the child exits (but before it's waited for) it becomes a "zombie". If it's never waited for (because the parent process is hung, for example) it remains a zombie.

I post just a small example for fork() and pipe()
http://www-h.eng.cam.ac.uk/help/tpl/unix/fork.html
0
 

Author Comment

by:avidamani
Comment Utility
1)The fork code :  
   ============
 if ((pid = fork()) < 0)
    {
        if (pipe_ok) {
            close(fd[0]);
            close(fd[1]);
        }
        return;
    }
    else
    {
        if (pid == 0)
        {
            // Close the read half of the pipe.
            if (pipe_ok)
                close(fd[0]);

            // I AM THE CHILD - transform into another process
            if (execlp(a_exec,
                       a_exec,
                       (char *)NULL) < 0)
            {
                 exit(2);
            }
        }



2) I am calling wait() in the signal handler. So the child will remain Zombie till its signal handler is called.
   
     c_pid = wait(&c_status);

    I understand the zombie concept but since I'm calling wait in the signal handler, and signal is the highest
    priority stuff in unix, even though parent is hung/busy, the signal handler should get called.
   
    Also I'm not sure why the signal handler is called again after I've kill/restarted the parent process, even though there was only 1 child that was killed and was in zombie state. Since init will adopt the zombie and clean it up as it is now an orphan.

Thanks
0
 
LVL 1

Expert Comment

by:fsign21
Comment Utility
The code for // I AM THE PARENT ?

I guess, you have a big project with GUI and it is difficult to post all you source...
If you want, you can send me the code to fsign21@gmx.net and I can have a look on it.
0
 

Author Comment

by:avidamani
Comment Utility
I cannot post the source code as its a proprierty thing. But yaa its a bif project :)
0
 

Author Comment

by:avidamani
Comment Utility
I was wondering what made the signal handler to get called after the parent process was killed. In this case, the init will take over the child and clean it up as child exited before parent was killed.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 45

Expert Comment

by:sunnycoder
Comment Utility
sorry for late reply.. I was away on a vacation ... were you able to solve the problem or is it still open?
0
 

Author Comment

by:avidamani
Comment Utility
The problem is still there..... :(
0
 
LVL 45

Expert Comment

by:sunnycoder
Comment Utility
>1 more thing, is it possible to miss a signal if theparent process is very busy processing something else
no

>Cause i know for sure that if i do not close the reading end of the pipe after the child exits
as far as I remember, you should be closing the read end first

>SIGPIPE signal comes when you write to a pipe which has no reader. right?
right

>Is there anything that tells that the pipe is empty from which you are reading, i.e. there is no writer to it.
No signal but reads will return nothing... that is sufficient diagostic that no data is available

>and signal is the highest priority stuff in unix,
some interrupts have higher priority

>why the signal handler is called again after I've kill/restarted the parent process
this is strange and I am surprised too... add some code to signal handler and in that signal handler print the ID of the process which sent the signal... to get this id print the si_pid member of siginfo_t .. also try running the code through a debugger

>init will adopt the zombie and clean it up as it is now an orphan.
no, it wont clean it up
0
 

Author Comment

by:avidamani
Comment Utility
The signal handler is getting called in the next process with pid of -1
0
 
LVL 45

Expert Comment

by:sunnycoder
Comment Utility
is it a daemon process? are you using setsid() or fork to make it process group leader ?
0
 

Author Comment

by:avidamani
Comment Utility
Yes it is... It gets restarted as soon as it gets killed from inittab.
I'll try to explain the scenario again.

1) client makes a call.
2) This process forks off a child.
3) The child exits and becomes a zombie.
4) The parent at times hits the signal handler .. at times dont
5) I kill the parent after some time (once after 1 day)
6) The new process gets respawned from inittab entry
7) Its signal handler gets hit and the child pid is shown as -1 when i do a wait in the signal handler.

I want to know why the signal handler of the new process gets hit. It didn't do a fork() or setsid(). Fork() was done by the previous process which I killed.
0
 
LVL 45

Expert Comment

by:sunnycoder
Comment Utility
2) This process forks off a child.
3) The child exits and becomes a zombie.
4) The parent at times hits the signal handler .. at times dont

I am sure you are missing out on something in your code ... Check it again or still better ask someone else to do it for you .... IPC mechanism is a time-tested mechanism which has stood for decades now ... This is an issue with your code.

>7) Its signal handler gets hit and the child pid is shown as -1 when i do a wait in the signal handler.
how do you get the child pid ? pid of -1 is invalid for a sending process... However, it is possible to send a signal to pid -1. This would send a signal to all the processes in the group except the first one
0
 
LVL 18

Expert Comment

by:liddler
Comment Utility
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

PAQ  No refund

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

liddler
EE Cleanup Volunteer
0
 

Accepted Solution

by:
modulo earned 0 total points
Comment Utility
PAQed - no points refunded (of 230)

modulo
Community Support Moderator
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Suggested Solutions

Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now