2012-11-06 84 views
1

我想添加一個新功能,以擴展應用程序開始執行另一個應用程序使用fork(2)和exec(3)(當前execl)。如何處理fork-exec上的共享內存和共享信號量?

不幸的是,應用程序使用共享內存,共享信號量和大量的打開文件描述符,當調用fork時它們都被複制。我知道我應該在子進程中調用execl之前關閉所有文件描述符,共享資源等,但其中的一部分由第三方庫處理,我無法訪問它們。

最重要的是它的所有應用程序都是線程化的(使用posix線程),但只要在子進程中fork和exec之間沒有異步系統調用(根據http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them),就應該可以。

我現在面臨的問題是,execl調用似乎以某種方式損壞共享資源,導致使用它們的線程發生死鎖。這似乎只發生在調用execl作爲退出子進程立即退出後用_exit(2)不會產生此行爲時發生。

使用fork和exec產生新進程時,處理共享內存和共享信號量的正確方法是什麼?

回答

1

很可能是因爲沒有關閉子文件描述符而導致死鎖。 之前嘗試別的試試這個:在孩子/proc/[pid]/fd

迭代通過所有的文件描述符,並調用exec之前關閉它們。

如果這不行,那麼您必須將所有內存(除了堆棧幀之外)標記爲MADV_DONTFORKmadvise。您可以通過將映射範圍與本地線程堆棧上的任何指針進行比較,從/proc/[pid]/maps和本地堆棧幀中獲取所有當前映射的列表。

+0

感謝您的提示,我現在使用下面的代碼以關閉所有文件描述符的子進程: – kassiopeia

+0

感謝您的提示,我現在使用下面的代碼以關閉所有文件描述符的子進程: – kassiopeia

+0

DIR * hdir = opendir(「/ proc/self/fd /」); struct dirent * entry; int fd; ((entry = readdir(hdir))!if(hdir!= NULL){ if(hdir!= NULL){ fd = strtol(entry-> d_name,NULL,10); (fd> 2) close(fd);如果(fd> 2) close(fd); } closedir(hdir); } – kassiopeia

1

這裏可能存在多個問題,包括fork()和exec()代碼中的錯誤,甚至是程序使用共享內存和信號量的錯誤。

處理此問題的一種可能方法是使用system()函數。

這將在shell環境中運行一個命令並阻塞,直到程序退出。你可以產生一個新的線程,然後調用系統。讓內置函數處理正確的fork()和exec()。

如果你仍然有問題,那麼我會說你的共享mem/semaphores與fork和exec不兼容。

1

這裏再一次我現在用來關閉所有文件描述符的代碼(在評論中看起來不太好)。

DIR* hdir = opendir("/proc/self/fd/"); 
    struct dirent* entry; 
    int fd; 

    if (hdir != NULL) { 
     while ((entry = readdir(hdir)) != NULL) { 
      fd = strtol(entry->d_name, NULL, 10); 

      if (fd > 2) 
       close(fd); 
     } 

     closedir(hdir); 
    } 

這使我關閉了一打文件描述符。