[英]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;
}
有迹象表明,你不需要调用析构函数的任何两者之间出色的赔率fork
和exec
。 是的, fork
会复制整个进程状态,包括具有析构函数的对象, exec
删除所有状态。 但它真的重要吗? 来自程序外部的观察者 - 在同一台计算机上运行的另一个不相关的进程 - 可以告诉那些析构函数不会在孩子身上运行吗? 如果无法辨别,则无需运行它们。
即使外部观察者可以说,在孩子身上运行析构函数也可能是错误的。 通常的例子是:假设你在调用fork
之前向stdout
写了一些东西,但是它在库中被缓存了,所以实际上还没有被传递到操作系统。 在这种情况下,你不能在孩子的stdout
上调用fclose
或fflush
,否则输出会发生两次! (这也是为什么你几乎肯定应该调用_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.