6

我有一个分叉给子进程的进程。如果父进程存在,则子进程不应该存在。

所以,如果父进程死了,我会调用::prctl(PR_SET_PDEATHSIG, SIGKILL)子进程来杀死它。

最终发生的是父线程调用pthread_exit,并且该线程最终成为杀死子进程的催化剂。

这是我的代码:

父级.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;
}

孩子.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;
}

在命令行上运行以下命令:

$ ./parent

同时,运行以下命令查找 child 的状态:

$ for i in {1..10000}; do ps aux | grep child ; sleep .5; done

孩子没了。如果您在 child 中取出 prctl 调用,它不会失效。

prctl 手册页似乎描述了这个调用应该SIGKILL在父进程死亡时调用,而不是父线程。

当父进程而不是父线程死亡时,有什么方法可以让 prctl 杀死子进程?

4

1 回答 1

6

PR_SET_PDEATHSIG子进程死亡是因为它在父线程死亡时收到信号。这意味着当创建它的线程死亡时它会收到一个信号。因此,如果您希望子进程依赖于父进程(我假设您的意思是“主”函数死亡时),则从执行父进程的主线程分叉。如果您在Linux prctl(2) 手册页中查找手册页,他们会明确指出是创建此进程的线程,将信号传递给调用(在您的情况下为子进程)进程:

警告:在这种情况下,“父”被认为是 创建此进程的线程。换句话说,信号将在该线程终止时发送(例如,通过 pthread_exit(3)),而不是在父进程中的所有线程终止后发送。

底线:如果您希望它依赖于父进程的执行,则从执行的主线程分叉。简而言之,不要创建线程来分叉子进程,只需从主线程分叉即可。

于 2015-11-07T00:27:23.633 回答