[英]c++ runtime_error catching not consistent across cluster nodes
我正在嘗試設置一個可以在Redhat Scientific Linux(v5.11)集群上運行的c ++程序。 我已經能夠編譯該軟件,並且它可以在頭節點上完美運行,但是在任何工作節點上運行時,它都會崩潰。
我已將此問題追溯到部分代碼,如果某些條件返回false,則會引發std::runtime_error
。 這是有意為之的,因為當軟件正確運行時,它會被捕獲並繼續迭代。 在工作程序節點上,首次引發錯誤時,軟件將中止。 abort
代碼和backtrace
顯示如下。
因為它可以在一個節點上運行,但不能在其他節點上運行,所以我猜這是gcc版本的問題。 要進行編譯,我必須yum install devtoolset-2
並使用gcc 4.8.2 (Red Hat 4.8.2-15)
構建軟件,因為系統gcc 4.1.2 (Red Hat 4.1.2-55)
太舊而無法正確編譯。 。 當我在兩個節點上啟動應用程序時,我將具有以下內容:
which gcc > /opt/rh/devtoolset-2/root/usr/bin/gcc
which c++ > /opt/rh/devtoolset-2/root/usr/bin/c++
which g++ > /opt/rh/devtoolset-2/root/usr/bin/g++
which gfortran > /opt/rh/devtoolset-2/root/usr/bin/gfortran
$LD_LIBRARY_PATH > /opt/rh/devtoolset-2/root/usr/lib64:/opt/rh/devtoolset-2/root/usr/lib
就頭節點和工作節點之間的區別而言,除了內核版本外,它們是相同的:
我累的事情:
-V
傳遞環境) ssh worker
直接在worker節點上運行,並導出與根節點上所有相同的環境變量 任何幫助將不勝感激! 我認為以下幾個問題會為您解答,這有助於我縮小原因:
abort
如下:
terminate called after throwing an instance of 'std::runtime_error'
what(): 'custom error message'
Program received signal SIGABRT, Aborted.
0x00000038b6830265 in raise () from /lib64/libc.so.6
backtrace
如下:
#0 0x00000038b6830265 in raise () from /lib64/libc.so.6
#1 0x00000038b6831d10 in abort () from /lib64/libc.so.6
#2 0x00000038bb0bec44 in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib64/libstdc++.so.6
#3 0x00000038bb0bcdb6 in ?? () from /usr/lib64/libstdc++.so.6
#4 0x00000038bb0bcde3 in std::terminate() () from /usr/lib64/libstdc++.so.6
#5 0x00000038bb0bceca in __cxa_throw () from /usr/lib64/libstdc++.so.6
#6 0x00002aaaab074bdc in Some::Function::Name() () from path/to/file.so
我必須承認我對c ++的了解非常有限,盡管iv在過去兩天一直在努力改進,但iv一直在與這個問題作斗爭。 這是引發並捕獲錯誤的代碼的簡化示例(這顯然是重復調用Func1
更大過程的一部分):
double Func1(int a, double b, int c)
{
for (bool OK = true ; OK && d > e && f < a ; f++)
{
try
{
for (d = 0, g = 1 ; g < 10 ; g *= 2)
{
Func2() ;
}
}
catch (runtime_error problem)
{
*log << problem.what() ;
OK = false ;
}
if (c > 1)
{
*log << f << d;
}
}
void Func2()
{
for (int j = 0 ; j < ny && (x & 5) > 0 ; j++)
{
if (Func3(j) <= 0.0)
{
throw runtime_error("custom error message") ;
}
Func4[j] = j ;
}
}
在編譯的程序上運行ldd
(在頭節點上運行,工作節點上缺少第1行):
linux-vdso.so.1 => (0x00007fff2b6e7000)
/users/username/software/version/Part1/Part1Extra.so (0x00002b3543587000)
libgfortran.so.3 => /usr/lib64/libgfortran.so.3 (0x00002b354385b000)
libm.so.6 => /lib64/libm.so.6 (0x0000003cc2000000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000000315f800000)
libc.so.6 => /lib64/libc.so.6 (0x0000003cc1c00000)
/users/username/software/version/Part2/Part2.so (0x00002b3543b4f000)
/users/username/software/version/Part3/Part3.so (0x00002b3543d9b000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x0000003160000000)
/lib64/ld-linux-x86-64.so.2 (0x0000003cc1800000)
/users/username/software/version/Part3/Part3Extra.so (0x00002b3543fb2000)
終於設法弄清楚發生了什么...
對於那些發現與c ++代碼有關的意外錯誤的人,即使系統共享一個公共文件結構,該錯誤通常可以在多節點系統的一部分上正常運行,而在其他部分卻不能正常運行,盡管我敢肯定,這最后一點可能會引起誤解對於那些更熟悉系統管理的人來說,這是顯而易見的。
最初,我的印象是頭節點和工作節點/計算節點共享整個文件結構。 這只是部分正確,因為工作節點可以訪問文件系統的某些部分,但重要的是不能訪問核心文件,例如/lib
和/lib64.
基本上,所有通過yum
安裝的軟件包都獨立於每個計算節點。 將頭節點更新為正確的gcc
版本(在本例中為devtoolset-2
)后,我的印象是每個工作節點也都進行了更新。 此情況並非如此。
使用gcc 4.8.2 (Red Hat 4.8.2-15)
編譯的C ++代碼在具有libstdc++.x86_64 (v4.1.2-55.el5)
的頭節點上工作,捕獲了引發std::runtime_error
錯誤。 在工作節點上運行時未正確捕獲此錯誤。
問題在於工作程序節點系統libstdc++.x86_64
版本較舊(不幸的是,我不記得確切的版本),這意味着沒有發現錯誤。 某些版本的libstdc++
似乎無法捕獲使用gcc 4.8.2
編譯的代碼中的錯誤。
每個工作節點都必須使用yum
進行手動更新,以使其libstdc++
版本足夠高以解決此問題(在本例中為v4.1.2-55.el5
)。 更新libstdc++
解決此問題。
在我們的情況下,工作節點無法直接連接到這樣的互聯網yum
不得不通過代理完成。 我們的yum
版本也太舊了,無法使用socks5h
自動ssh隧道代理方法。 因此,我們必須在頭節點上使用squid
包來允許連接。
最終,花了一段時間才弄清文件結構的差異是非常令人誤解的。 雖然密鑰文件夾不在節點之間共享,但是那里的內容看起來與舊/新版本的軟件包具有完全相同的文件結構,只是內容有所修改。
再一次,這對於系統管理員來說可能是非常明顯的,但是您就可以了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.