13
votes

I am into this weird behaviour where I have my main program and a forked child. They are piped like this(the numbers are file descriptors):

 ___parent___
|            |                     ____child_____
| 0 stdin    |                    |              |
| 1 pipe1[1]----------.           |  1 stdout    |
| 2 pipe2[1]----------.\          |  2 stderr    |
|____________|         \`----------> 3 pipe1[0]  | 
                        `----------> 5 pipe2[0]  |
                                  |______________|

So parent gets input from stdin but redirects stdout and stderr to two pipes. The child has closed its stdin and uses the read ends of the pipes instead.

Then I have a function to just kill the child:

void killChild(){
  printf("Killing %d\n", (int)childID);
  fflush(stdout);
  kill(childID, SIGKILL);
  waitpid(childID, NULL, 0);   // getting rid of the zombie
}

The child gets succesfully killed but the problem is that the parent itself gets killed as well. I checked the PID of the child and it's correct.

So why does the parent die?

2
I love the name of this question. And the art. - Gabriel
What signal did the parent receive? - hochl
Does the parent attempt to write to stdout or stderr after killing the child? If so, it dies because of the SIGPIPE. Are you changing handling of SIGCHLD? - William Pursell

2 Answers

13
votes

Any attempt by the parent to write to its fd 1 or fd 2 after the child exits will result in the kernel sending SIGPIPE to the parent. The default behavior for SIGPIPE is process termination. That's probably what's happening.

3
votes

You need to handle SIGPIPE and SIGCHLD signals - possibly just ignore them - and you should be fine.