当父线程退出而不是父进程退出时调用prctl(PR_SET_PDEATHSIG,SIGNAL)

7
我有一个进程,正在派生一个子进程。如果父进程不存在,则子进程不应存在。
因此,我在子进程中调用::prctl(PR_SET_PDEATHSIG, SIGKILL)以确保子进程在父进程终止时退出。
但实际情况是,父线程调用pthread_exit,并且该线程成为终止子进程的催化剂。
以下是我的代码: 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;
}

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

$ ./parent

同时,运行以下命令以查找子进程的状态:
$ for i in {1..10000}; do ps aux | grep child ; sleep .5; done

子进程失效了。如果在子进程中删除prctl调用,它就不会失效。

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

是否有办法让prctl在父进程死亡时杀死子进程而不是父线程?

1个回答

9
子进程会因为接收到PR_SET_PDEATHSIG信号而死亡,当创建它的父线程死亡时就会发送该信号。也就是说,当创建它的线程死亡时,它会收到一个信号。因此,如果您希望子进程依赖于父进程(我假设您指的是“main”函数死亡时),请从父进程的主线程中进行fork操作。如果您在Linux prctl(2) man page上查看手册页面,它们明确指出,是创建此进程的线程向调用(在您的情况下是子进程)进程传递信号:

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

最重要的是: 如果您希望子进程依赖于父进程的执行,请从父进程的主线程中进行fork操作。简单地说,不要创建一个线程来fork子进程,只需从主线程中fork即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接