Security

如何檢查,超出了哪個限制?(程序因 ulimit 而終止。)

  • November 12, 2013

假設程序在 ulimited 環境中執行:

(
ulimit  ... -v ... -t ... -x 0 ...
./program
)

程序終止。

可能有很多原因:超出記憶體/時間/文件限制;只是簡單的段錯誤;甚至返回程式碼為 0 的正常終止。

如何在不修改程序的情況下檢查程序終止的原因是什麼?

PS我的意思是“當給出二進製文件時”。也許一些包裝器(ptrace-ing 等)可能會有所幫助?

一般來說,我認為你不能不幸。(某些作業系統可能會提供它,但我不知道我所知道的支持這一點的作業系統。)

資源限制的參考文件:getrlimit來自 POSIX 2008。

以 CPU 限制為例RLIMIT_CPU

  • 如果程序超過軟限制,它會被發送一個SIGXCPU
  • 如果程序超過硬限制,它會得到一個普通的SIGKILL

如果你可以wait()在你的程序上,你可以判斷它是否被SIGXCPU. 但是您無法區分SIGKILL因違反硬性限製而被派遣的人員與來自外部的普通老殺。更重要的是,如果程序處理XCPU,你甚至不會從外面看到它。

同樣的事情RLIMIT_FSIZE。如果程序不處理它,您可以SIGXFSZ從狀態中看到。wait()但是一旦超過文件大小限制,唯一發生的事情就是嘗試再次測試該限制的進一步 I/O 將簡單地接收EFBIG- 這將由程序內部處理(或不處理,不幸的是)。如果程序處理SIGXFSZ,與上面相同 - 你不會知道它。

RLIMIT_NOFILE? 好吧,你甚至沒有收到信號。open和朋友們剛回到EMFILE節目。它不會受到其他困擾,因此無論在那種情況下它被編碼為失敗的方式,它都會失敗(或不失敗)。

RLIMIT_STACK? 好舊SIGSEGV,無法與其他原因的得分區分開來。(你會知道那是殺死程序的原因,從wait狀態。)

RLIMIT_AS並且RLIMIT_DATA只會 makemalloc()和其他一些開始失敗(或者SIGSEGV如果在嘗試在 Linux 上擴展堆棧時達到 AS 限制,則接收)。除非程序寫得很好,否則它可能會在那時相當隨機地失敗。

所以簡而言之,一般來說,失敗要麼與其他程序死亡原因沒有明顯不同,所以你不能確定,或者可以完全從程序中處理,在這種情況下,它決定是否/何時/如何繼續,而不是你從外部。

據我所知,你能做的最好的事情就是編寫一些程式碼來分叉你的程序,等待它,然後:

  • 檢查退出狀態以檢測SIGXCPUSIGXFSZ(AFAIK,這些信號只會由作業系統生成用於資源限制問題)。根據您的確切需求,您可以假設這SIGKILLSIGSEGV與資源限制有關,但這有點牽強。
  • 看看你可以從getrusage(RUSAGE_CHILDREN,...)你的實現中得到什麼,以了解其他的。

可能存在特定於作業系統的工具來提供幫助(可能是ptrace在 Linux 或 Solaris 上dtrace),或者可能是調試器類型的技術,但這將與您的特定實現更加相關。


(我希望其他人會用一些我完全不知道的魔法來回答。)

引用自:https://unix.stackexchange.com/questions/23275