2010-03-22 14 views
7

我試圖追查一個非常奇怪的崩潰。奇怪的是有人發現了一個解決方法,我無法解釋。exec如何改變exec'ed程序的行爲

的解決方法是這樣的小程序,我稱之爲「轉輪」:

#include <stdio.h> 
#include <unistd.h> 
#include <string.h> 
#include <errno.h> 

int main(int argc, char *argv[]) 
{ 
    if (argc == 1) 
    { 
     fprintf(stderr, "Usage: %s prog [args ...]\n", argv[0]); 
     return 1; 
    } 

    execvp(argv[1], argv + 1); 

    fprintf(stderr, "execv failed: %s\n", strerror(errno)); 

    // If exec returns because the program is not found or we 
    // don't have the appropriate permission 
    return 255; 
} 

正如你所看到的,這一切的程序做的是使用execvp用不同的方案來取代自己。

程序崩潰時,它是直接在命令行調用:

/path/to/prog args # this crashes 

但是當它被間接地通過我的亞軍墊片調用工作正常:

/path/to/runner /path/to/prog args # works successfully 

對於我的生活,我可以弄清楚如何讓一個額外的exec可以改變正在運行的程序的行爲(正如你所看到的程序不會改變環境)。

關於崩潰的一些背景知識。崩潰本身發生在C++運行時。特別是,當程序執行throw時,崩潰版本錯誤地認爲沒有匹配的catch(雖然有)並調用terminate。當我通過跑步者調用程序時,異常被正確捕捉。

我的問題是任何想法爲什麼額外的EXEC會改變exec'ed程序的行爲?

+0

我不知道:但是execvp會改變工作目錄嗎?你傳遞了什麼論點? – 2010-03-22 20:22:12

+0

@MartinYork - AFAIK,'execvp'永遠不會改變工作目錄(這需要調用'chdir',而runner不會這麼做)。具體的論點是不相關的;所描述的行爲與傳遞給程序的特定參數無關。 – 2010-03-22 20:39:23

+1

如果您使用'execv()'而不是'execvp()'做同樣的事情嗎? – caf 2010-03-23 01:47:55

回答

3

運行程序加載的.so文件可能導致runee正常工作。嘗試每個二進制文件,看看是否有任何庫加載不同的版本/位置。

+1

問題在於'ld-linux.so.2'是否將特定的共享對象映射到主二進制之前或之後的地址空間中(實際的錯誤在其他地方,但由於環境的原因,錯誤僅在SO映射到一個較低的地址,然後是主二進制)。 – 2010-03-26 23:27:42

0

作爲一個黑暗中的鏡頭:雙執行可能會改變RAM中環境變量的順序。

環境是指針的內存結構;內核將該結構複製到新進程的地址空間中。 RAM中元素的實際順序可能會在該副本期間發生更改(環境變量未按語義排序,但RAM中的地址有順序)。使用兩個exec(),該訂單可能會被修改兩次。

RAM中的字符串排序發生變化,發現一個bug有點奇怪,但發生了一些奇怪的事情。

+0

感謝您的建議,但似乎並不是這樣。我傾銷了原始環境塊,並且它們的順序都是相同的。 – 2010-03-22 21:15:24

0

我不知道你是否在argv [0]中傳遞了一些不同的東西給shell。我從上面寫的東西中看不到明顯的東西,但是可能會將argv [0]設置爲程序的實際第一個參數,而shell將其設置爲其名稱(例如完整路徑或短路徑)

+0

@MarkR - 感謝您的建議。我修改了runner,使得'argv [0]'不包含路徑。不幸的是,我仍然看到相同的行爲。 – 2010-03-22 23:07:10

1

也許被調用的程序有內存泄漏。嘗試使用valgrind或其他內存檢查工具運行它。在發生內存錯誤之後,其他一切都是未定義的行爲(所以一切都可能發生)。

+0

除了在出口塊處仍然可以正常訪問,Valgrind在檢測到終止版本(或者不終止版本)時沒有檢測到任何錯誤。 – 2010-03-23 18:18:22

0

我猜你可以比較'working'和'crashing'版本之間的兩件事情 - 打開文件描述符和信號處理程序 - 這些可以通過exec傳遞。

我不明白他們是如何不同的問題,但它可能是值得消除它們。