[英]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.