簡體   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