I have a process that is forking to a child process. The child process should not exist if the parent process exists. So, I call ::prctl(PR_SET_PDEATHSIG, SIGKILL) in the child process to kill it if the parent dies. What ends up happening is the parent thread calls pthread_exit, and that thread ends up being the catalyst that kills the child process.
Here is my code:
parent.cpp:
#include <sys/prctl.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <iostream>
void* run(void* ptr) {
std::cout << "thread:" << getpid() << ":" << std::hex << pthread_self() << ":" << std::dec << getppid() << std::endl;
auto pid = fork();
if ( pid != 0 ) {
sleep(1);
}
else {
char* arg = NULL;
execv("./child", &arg);
}
return NULL;
}
int main() {
std::cout << "main:" << getpid() << ":" << std::hex << pthread_self() << ":" << std::dec << getppid() << std::endl;
pthread_t threadid;
pthread_attr_t attr;
::pthread_attr_init( &attr );
::pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
::pthread_create(&threadid,&attr,run,NULL);
sleep(6);
return 0;
}
child.cpp:
#include <sys/prctl.h>
#include <signal.h>
#include <unistd.h>
#include <iostream>
int main() {
std::cout << "child:" << getpid() << ":" << std::hex << pthread_self() << ":" << std::dec << getppid() << std::endl;
::prctl( PR_SET_PDEATHSIG, SIGKILL );
sleep(6);
return 0;
}
Run the following on the command line:
$ ./parent
At the same time, run the following to find the status of child:
$ for i in {1..10000}; do ps aux | grep child ; sleep .5; done
Child goes defunct. If you take out the prctl call in child, it does not go defunct.
The prctl page at http://www.kernel.org/doc/man-pages/online/pages/man2/prctl.2.html seems to describe that this call should call SIGKILL when the parent process dies, not the parent thread. Is there any way to make prctl kill the child when the parent process dies instead of the parent thread?
You need to understand a couple things about threading (my knowledge is from C, but this implementation seems to match what I did in C for the most part)
A process is a big, heavy thing that can contain multiple threads, as I'm sure you know.
What I believe is happening here: the parent thread is killed, and the child thread never receives any signal that it should die, as well.
You need to make sure when your process ends, it is broadcasting that to all threads it contains, not just a parent thread.
This is demonstrated well by the following graph from the LLNL tutorial on POSIX threads:
I think the fix is just to make sure you call pthread_join when you initialize your threads.
Hope this helps!
The child process dies because it receives
PR_SET_PDEATHSIG
signal when the parent thread dies. What it means is that it gets a signal when the thread that created it dies. So if you want the child to depend on the parent process (I assume you mean when the "main" function dies) fork from the main thread of execution of your parent process. If you look up the man pages at Linux prctl(2) man page they specifically state that it is the thread which created this process, delivers the signal to the calling (In your case the child) process:Bottom line: Fork from the main thread of execution if you want it to depend on the parent process's execution. In simpler words, don't create a thread to fork the child process, just fork it from the main thread.