簡體   English   中英

C ++ runtime_error捕獲在群集節點之間不一致

[英]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

就頭節點和工作節點之間的區別而言,除了內核版本外,它們是相同的:

  • 頭:Linux address.com 2.6.18-419.el5#1 SMP x86_64 x86_64 x86_64 GNU / Linux
  • 工作者:Linux address.com 2.6.18-164.11.1.el5#1 SMP x86_64 x86_64 x86_64 GNU / Linux

我累的事情:

  • 使用SGE隊列提交在工作節點上運行(通過-V傳遞環境)
  • 通過ssh worker直接在worker節點上運行,並導出與根節點上所有相同的環境變量
  • 在工作節點上編譯並運行

任何幫助將不勝感激! 我認為以下幾個問題會為您解答,這有助於我縮小原因:

  1. 追求內核版本差異是否可行?
  2. 這看起來像是庫和路徑而不是代碼的問題嗎?
  3. 庫版本之間c ++錯誤處理的方式是否有所改變?
  4. 我還有其他調試方法可以嘗試找出原因嗎?

額外信息

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM