【问题标题】:Daemon child can't execute library守护进程子进程无法执行库
【发布时间】:2015-10-22 05:45:22
【问题描述】:

我正在编写一个 Linux 守护程序来执行我的代码。我的代码调用了第三方库。如果我从父级执行我的代码,那么一切运行正常,但如果我直接从一个子级执行我的代码,则对第三方库的调用永远不会返回。如果我创建了第二个可执行文件来执行我的代码,并且我让守护进程运行该可执行文件,那么一切都运行良好。

为什么我不能从子进程调用我的代码?

int main(void)
{
    // Our process ID and Session ID
    pid_t pid, sid;

    fflush(stdout);

    // Fork off the parent process
    pid = fork();
    if (pid < 0)
        exit(EXIT_FAILURE);

    // If we got a good PID, then we can exit the parent process.
    if (pid > 0)
        exit(EXIT_SUCCESS);

    // Change the file mode mask
    umask(0);

    // Open any logs here
    close(STDIN_FILENO);
    close(STDOUT_FILENO);
    close(STDERR_FILENO);
    if (open("/dev/null",O_RDONLY) == -1)
        exit(EXIT_FAILURE);
    if (open("/dev/null",O_WRONLY) == -1)
        exit(EXIT_FAILURE);
    if (open("/dev/null",O_WRONLY) == -1)
        exit(EXIT_FAILURE);

    // Create a new SID for the child process
    sid = setsid();
    if (sid < 0)
        exit(EXIT_FAILURE);

    // Change the current working directory
    if ((chdir("/")) < 0)
        exit(EXIT_FAILURE);

    // doesn't work
    MyObject ob;
    ob.start();

    // works
    //execlp("/home/root/NextGenAutoGuidance", "NextGenAutoGuidance", (char*)NULL);


    while(1)
    {
        sleep(60);
    }

    exit(EXIT_SUCCESS);
}

我尝试将我的对象的对象声明作为全局和静态全局,我也尝试过对我的对象进行新建/删除。

调用第三方库返回的唯一方法是我的对象是从父进程启动的。

如何创建守护程序,这样我就不必调用外部二进制文件来正确运行?

编辑

我需要补充一点,我也尝试过不杀死父母,我也遇到了同样的问题。

【问题讨论】:

  • 库代码有什么作用?它不工作的症状是什么?
  • 处理CAN总线通信,不是cansocket库
  • 关于MyObject的分配,如果你尝试new MyObjectob-&gt;start(),子进程会成功吗?
  • 不,我也试过了。
  • 嗯。如果你将MyObject 结构移到fork 之前?

标签: c++ linux daemon


【解决方案1】:

经过数小时的挖掘,我找到了问题的原因和解决方案。

原因:

我在 MyObject 类中有一个私有全局静态类对象,它启动了一个调用第三方库的线程。

因为类对象是全局的,所以它是在 fork 之前创建的,即使我在 fork 之后声明了 MyObject。一旦创建了静态类对象,它就会启动一个调用第三方库的线程,并且在库函数中它遇到了一个互斥锁。当你 fork 线程没有被复制时,所以在 fork 之后父进程被杀死并且子进程创建了一个新的静态类对象,该对象启动了一个新线程,该线程调用了库函数并来到了同一个互斥锁。由于在离开库函数之前被杀死,父进程没有释放互斥锁,因此子进程卡在等待释放互斥锁。

解决方案:

不要在创建对象时创建线程,并等待子创建线程直到分叉之后。

【讨论】: