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 man page 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?
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:
Warning: the "parent" in this case is considered to be the thread that created this process. In other words, the signal will be sent when that thread terminates (via, for example,
pthread_exit(3)
), rather than after all of the threads in the parent process terminate.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With