繁体   English   中英

发布C ++资源和fork-exec?

[英]Releasing C++ resources and fork-exec?

我正在尝试使用fork-exec从我的C ++项目中生成一个新进程。 我正在使用fork-exec来创建子进程的双向管道。 但是我担心分叉进程中的资源不会被正确释放,因为exec-call将完全接管我的进程并且不会调用任何析构函数。

我尝试通过抛出异常并在main的末尾从catch块调用execl来绕过这个,但是这个解决方案并没有破坏任何单例。

有没有明智的方法来安全地实现这一目标? (希望避免任何atExit黑客攻击)

例如:以下代码输出:

We are the child, gogo!
Parent proc, do nothing
Destroying object

即使分叉进程也有一个单例的副本,在我调用execl之前需要对其进行破坏。

#include <iostream>
#include <unistd.h>

using namespace std;

class Resources
{
public:
    ~Resources() { cout<<"Destroying object\n"; }
};

Resources& getRes()
{
    static Resources r1;
    return r1;
}

void makeChild(const string &command)
{
    int pid = fork();
    switch(pid)
    {
    case -1:
        cout<<"Big error! Wtf!\n";
        return;
    case 0:
        cout<<"Parent proc, do nothing\n";
        return;
    }
    cout<<"We are the child, gogo!\n";
    throw command;
}

int main(int argc, char* argv[])
{
    try
    {
        Resources& ref = getRes();
        makeChild("child");
    }
    catch(const string &command)
    {
        execl(command.c_str(), "");
    }
    return 0;
}

有迹象表明,你不需要调用析构函数的任何两者之间出色的赔率forkexec 是的, fork会复制整个进程状态,包括具有析构函数的对象, exec删除所有状态。 但它真的重要吗? 来自程序外部的观察者 - 在同一台计算机上运行的另一个不相关的进程 - 可以告诉那些析构函数不会在孩子身上运行吗? 如果无法辨别,则无需运行它们。

即使外部观察者可以说,在孩子身上运行析构函数也可能是错误的。 通常的例子是:假设你在调用fork之前向stdout写了一些东西,但是它在库中被缓存了,所以实际上还没有被传递到操作系统。 在这种情况下,你不能在孩子的stdout上调用fclosefflush ,否则输出会发生两次! (这也是为什么你几乎肯定应该调用_exit而不是exit如果exec失败。)

说了这么多,有两种常见的情况,你可能需要在孩子身上做一些清理工作。 一个是文件描述符( 不要将它们与stdio FILE或iostream对象混淆),这些描述符应该在exec之后打开。 处理这些正确的方法是设置FD_CLOEXEC尽快标志上他们,他们被打开后(有些操作系统允许你这样做在open本身,但是这不是普遍的)和/或环3到一些大的在孩子中呼叫close不是 fclose )的号码。 (FreeBSD已经closefrom ,但就我所知,没有其他人这么做,这是一种耻辱,因为它非常方便。)

另一种情况是系统全局线程锁定 - 这是一个棘手且标准化程度较低的区域 - 可能会被父级和子级所占用,然后跨越exec继承到一个不知道它持有锁的进程。 这就是pthread_atfork应该用于的目的,但我已经读过,在实践中它并不能可靠地工作。 我能提供的唯一建议就是“当你拨打fork时不要拿任何锁”,对不起。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM