2013-07-29 118 views
-1

我正在用fork-exec模式編寫一些代碼,並且子進程打算在/ tmp目錄(append-create模式)中將文件寫入其輸出。 (該文件並不是事先存在的,而是在打開時創建的,或者至少應該是......)但是,我發現孩子在執行後無法打開任何文件。它可以在fork之前和exec之前打開/創建一個文件並寫入它,但在exec之後,我發現文件沒有被創建。此外,如果我在命令行運行該程序,我正在執行(使用相同的參數),它會創建該文件並將其寫入其中。只有從exec開始纔會出現這個問題。我真的不知道該如何開始思考這個問題......如果有人有在哪裏尋找線索的建議,我會非常感激!無法在fork-exec後打開文件

這裏有一個粗略的例子 - 注意,這是不是在運行:) 兒童實際代碼:

#define MSG "Opened file: " 
int main (usual stuff) { 
    const char* szTemp = "/tmp/helloworld"; 
    FILE* temp = fopen(szTemp, "a"); 
    fwrite(MSG, sizeof(char), strlen(MSG), temp); 
    fwrite(szTemp, sizeof(char), strlen(szTemp), temp); 
    fwrite("\n", sizeof(char), 1, temp); 
    fclose(temp); 
    // at this point, I see the file with the normal content when Child is run 
    // from the command line, but the file is not created if Child is created 
    // by a call to exec 
} 

家長:

int main(usual stuff) { 
    pid_t pid = fork(); 
    if (0 == pid) { 
     // fopen/fwrite works fine if I do it here! 
     exec(child-process); 
    } 
    // parent continues... 
} 
+0

發佈你的代碼可能會導致有用的反應。 – bmargulies

+0

我添加了一些說明性的代碼...我的實際代碼是整個系統的~20000行,正如我所說我很笨拙,不知道從哪裏開始尋找問題,所以我不知道哪個所有代碼的一小部分與您分享。如果任何人有關於我應該從哪裏開始尋找的建議,我可以嘗試提供一些代碼...... –

+0

我認爲您需要製作[SSCCE](http://sscce.org/)。很可能你會在製作一個小例子向我們展示問題的過程中發現實際問題。事實上,我知道有可能編寫一個正如你所描述的正確的程序,所以我們所能做的只是猜測那20000行代碼中可能會出現什麼問題。 – Casey

回答

0

好吧,我想它了!以下是發生了什麼事情:在exec之前觸及文件的代碼顯然被調用,並且做了它應該做的事情。主啓動後觸及文件的代碼不會觸及文件,因爲它從未運行過。該進程死於exec和main之間!

有很多方法可以發生,但在我的情況下,這是因爲它試圖加載共享對象(.so)文件(動態鏈接庫的Linux味道),但路徑不在LD_LIBRARY_PATH因此失敗。 (從命令行一切正常,因爲我的LD_LIBRARY_PATH確實包含了正確的目錄,但是我的進程從fork開始無法訪問該環境......)解決方案是簡單地使用exec的evnironment參數傳入一個正確的值LD_LIBRARY_PATH,然後子進程可以找到.so文件並正確啓動。

現在,這就是爲什麼它很難在這種情況下檢測到...通常,如果一個進程無法找到一個必要的.so當它開始時,它會給你一個信息(在stderr,我相信)讓你知道它找不到哪個庫。我的麻煩是父進程是一個守護進程,所以我關閉了stdin,stdout和stderr。當我fork時,孩子繼承了打開的文件描述符,但是由於標準流被關閉了,它沒有任何地方發送它的輸出。一旦我添加了代碼以使子進程向文件發送標準輸出& stderr(這是在fork和exec之間完成的),我能夠在輸出文件中看到錯誤消息。

我還挺幸運在這裏,雖然,因爲我加入了標準輸出/標準錯誤輸出(主要)無關的原因...