signals: stop child, parent told child died !

signals: stop child, parent told child died !

Post by Tristan Savatie » Tue, 05 Nov 1996 04:00:00



I found a strange problem with signals, and I was wondering
if it was a bug. I am running kernel 2.0.0 x86.

I have a process that calls fork() to spawn a child process.

When I send a SIGTSTOP (19) signal to the child process,
the parent process receives a SIGCHLD (17) signal.

I believe that this is incorrect: SIGCHLD tells the parent that
the child process has died/exited/terminated, and in this
case the child process is just stopped (and can be restarted
with SIGCONT), so the parent should not receive a SIGCHLD.

Could someone confirm the problem and tell me if that is
normal behavior or a bug ?  Is the same behavior observed
on other Unix platforms ? Is that the POSIX behavior ?

You can reproduce the problem with the small program enclosed.

Compile and run the program.  With ps, you can find the pids
of the parent and child (the child's pid is always greater than the
parent's pid).

When you do kill -19 <child's-pid>, you'll get the message:

pid <parent's-pid> received signal 17 (ignored)

Regards,


   "My karma ran over my dogma"

==============================================================
#include <stdio.h>
#include <signal.h>

void handler_ignore(sig)
        int     sig;
{
        printf("pid %d received signal %d (ignored)\n", getpid(), sig);
        signal(sig, handler_ignore);

Quote:}

void main()
{
        int     i;

        for (i = 1; i < 30; i++) {
                signal(i, handler_ignore);
        }

        fork();

        while (1) sleep(1);

Quote:}

==============================================================
 
 
 

signals: stop child, parent told child died !

Post by Ronald Wah » Wed, 06 Nov 1996 04:00:00



> I found a strange problem with signals, and I was wondering
> if it was a bug. I am running kernel 2.0.0 x86.

> I have a process that calls fork() to spawn a child process.

> When I send a SIGTSTOP (19) signal to the child process,
> the parent process receives a SIGCHLD (17) signal.

This is the correct behavior.

Quote:> I believe that this is incorrect: SIGCHLD tells the parent that
> the child process has died/exited/terminated, and in this
> case the child process is just stopped (and can be restarted
> with SIGCONT), so the parent should not receive a SIGCHLD.

SIGCHLD means that the status of the child process have changed.
You can give a flag to sigaction to ignore SIGCHLD from stopped
processes. For more info look at the manpage to sigaction(2).

ron

--

 \ WWW: http://www.tu-chemnitz.de/~row             \

   \ PGP key available by finger to my email address \

 
 
 

signals: stop child, parent told child died !

Post by Tristan Savatie » Tue, 12 Nov 1996 04:00:00



> This is not a bug, it is a feature (-:

> Actuakky when the child gets a signal stopping it you get SIGCHLD
> (asumming` you are not ignoring that signal of course).

Solaris claims that it is POSIX compliant, but on Solaris
I couldn't observe the same behavior (i.e. the parent does
not get SIGCHLD).

I don't have a POSIX spec handy.  Do you know what POSIX
says ? Is Linux Posix-compliant in this regard ?

Quote:> You can tell
> the different by testing the result of wait with WIFSTOPPED (check
> the header file but I think that the right number).

I tried.  Here is what I got:

1) wait() returns after a short time
2) the wait status tells me WIFSTOPPED(status) == 0
in both cases (child stopped or child killed).

And I don't understand why wait() does return even though
the child does not exit.

The man page for wait() seems to indicate that:

       The  wait  function suspends execution of the current pro-
       cess until a child has exited, or until a signal is deliv-
       ered  whose  action is to terminate the current process or
       to call a  signal  handling  function.

In this case the child process is just sleeping, so I
do not understand why wait() does not block.

In any case, the status returned by wait(&status) does not seem
to give me any indication, since WIFSTOPPED is zero
in both cases (child stopped or child killed with signal KILL).

The only difference that I could find in the status
between those two cases (child stopped or child killed)
is the value of WSTOPSIG(), but the man page
says that this value should be evaluated only when WIFSTOPPED
returns non-zero, which is not the case.

Regards,


   "My karma ran over my dogma"

 
 
 

signals: stop child, parent told child died !

Post by Ruediger Hels » Fri, 15 Nov 1996 04:00:00


There has been some confusion about differences between Linux and Solaris
with regard to SIGCHLD handling for stopped children.  I will give an
overview about what the differences are and how code should be written
to be portable.

|> > Actually when the child gets a signal stopping it you get SIGCHLD
|> > (asumming` you are not ignoring that signal of course).
|>
|> Solaris claims that it is POSIX compliant, but on Solaris
|> I couldn't observe the same behavior (i.e. the parent does
|> not get SIGCHLD).
|>
|> I don't have a POSIX spec handy.  Do you know what POSIX
|> says ? Is Linux Posix-compliant in this regard ?
|>
|> > You can tell
|> > the different by testing the result of wait with WIFSTOPPED (check
|> > the header file but I think that the right number).
|>
|> I tried.  Here is what I got:
|>
|> 1) wait() returns after a short time
|> 2) the wait status tells me WIFSTOPPED(status) == 0
|> in both cases (child stopped or child killed).
|>
|> And I don't understand why wait() does return even though
|> the child does not exit.
|>
|> The man page for wait() seems to indicate that:
|>
|>        The  wait  function suspends execution of the current pro-
|>        cess until a child has exited, or until a signal is deliv-
|>        ered  whose  action is to terminate the current process or
|>        to call a  signal  handling  function.
|>
|> In this case the child process is just sleeping, so I
|> do not understand why wait() does not block.
|>
|> In any case, the status returned by wait(&status) does not seem
|> to give me any indication, since WIFSTOPPED is zero
|> in both cases (child stopped or child killed with signal KILL).
|>
|> The only difference that I could find in the status
|> between those two cases (child stopped or child killed)
|> is the value of WSTOPSIG(), but the man page
|> says that this value should be evaluated only when WIFSTOPPED
|> returns non-zero, which is not the case.

The POSIX.1 function to set up signal handlers is `sigaction()'.  This
function takes a pointer to a structure which contains an element
`sa_flags'.  When the signal handler for SIGCHLD is established, the
handling of signals for stopped child processes can be controlled by
the flag SA_NOCLDSTOP.  If this flag is not set, a stopped child causes
a SIGCHLD sent to the parent; if this flag is set, the parent does not
get the signal.  So far, this is entirely portable between all POSIX.1
systems.

On the other side, the C standard function to set up a signal handler
is called `signal()'.  This function is, at least in its historical
implementation, quite limited; BSD and SYSV extended it in incompatible
ways, so POSIX replaced it by `sigaction()' and placed very few
restrictions on the implementation of `signal()'.  At least in Linux,
`signal()' is implemented as a wrapper around `sigaction()', setting
the `sa_flags' argument to SA_INTERRUPT|SA_NOMASK|SA_ONESHOT.  Note that
SA_NOCLDSTOP is missing!  This is why you get a SIGCHLD when you set up
the signal handler with `signal()' and a child process stops.  Obviously,
Solaris seems to set SA_NOCLDSTOP in the flags, so you do not get signals
when child processes stop.

From the side of the implementation, the behaviour of Solaris seems more
intuitive, so it would be reasonable to add the SA_NOCLDSTOP flag to the
`signal()' implementation of the Linux C library, though the current
behaviour is perfectly POSIX compliant.

From the side of the application programmer, use `sigaction()' to get
portable behaviour.

Now with respect to the result of `wait()':  `wait()' does not return
a status for stopped processes (which is one reason `signal()' should
be changed).  Instead, `wait()' hangs until a process terminates or a
signal is received.  The description of WIFSTOPPED not set is probably
the result of the evaluation of an invalid status code from `wait()'.
Use `waitpid(-1, &stat_val, WNOHANG|WUNTRACED)' in a loop inside the
SIGCHLD handler to get status of stopped children too.


 
 
 

signals: stop child, parent told child died !

Post by Ulrich Drepp » Sat, 16 Nov 1996 04:00:00



> From the side of the implementation, the behaviour of Solaris seems more
> intuitive, so it would be reasonable to add the SA_NOCLDSTOP flag to the
> `signal()' implementation of the Linux C library, though the current
> behaviour is perfectly POSIX compliant.

> From the side of the application programmer, use `sigaction()' to get
> portable behaviour.

The question should not be what is useful to do to make signal()
useful for programmer.  As you said, this function is provided only
for compatibility reasons.  signal() must only be compatible with the
old behaviour and this to my knowledge does not include the
SA_NOCLDSTOP flag.

No programmer should really use signal() and even when somebody does a
"port" to Linux s/he should try to replace it with a call to
sigaction().

--
-- Uli

Ulrich Drepper \    ,--------------------'   \  76149 Karlsruhe/Germany

 
 
 

1. Signals sent to child when parent dies (HPUX 10.+)

I have some ambiguous information on what (if any) signals a child
process receives if it's parent dies.  The platform I'd really like to
know this for is HPUX 10.10(20).

According to 'The Magic Garden Explained (SRV4)', 1994 section 4.11.3
page 247:

"If a process group leader terminates before its children, then each of
it's children are sent SIGCHLD".  

Unfortunately, the SIGCHLD handler in my CHILD doesn't fire when the
parent dies (a KSH that puts the child into the background with '&').
It does fire if I send it by hand.

Here's the description in Bach's 'The Design of The Unix Operating
System (SRV2/3)', 1990 section 7.3 page 213:

'If the exiting process is the process group leader associated with a
control terminal (probably not in my case since not login shell), the
kernel sends the 'hangup' signal to each process in the process group.

Am I in some nebulous land of subjective UNIX implemention?  Something
descended from Berkeley (maybe I should get the daemon book)?

What's the deal?

Thanks,
bdw

2. Sharing X apps?

3. Stop parent if child dies

4. I/O conflicts

5. Getting a child and child's child process-id

6. WWW server?

7. FTP Server inside firewall

8. How a child tell if a parent is alive/dead ?

9. Keeping a child process alive when parent dies

10. How to notify a child that parent has died?

11. Parent's Accept died after Child proc terminated.