如何檢查,超出了哪個限制?(程序因 ulimit 而終止。)
假設程序在 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 限制,則接收)。除非程序寫得很好,否則它可能會在那時相當隨機地失敗。所以簡而言之,一般來說,失敗要麼與其他程序死亡原因沒有明顯不同,所以你不能確定,或者可以完全從程序中處理,在這種情況下,它決定是否/何時/如何繼續,而不是你從外部。
據我所知,你能做的最好的事情就是編寫一些程式碼來分叉你的程序,等待它,然後:
- 檢查退出狀態以檢測
SIGXCPU
和SIGXFSZ
(AFAIK,這些信號只會由作業系統生成用於資源限制問題)。根據您的確切需求,您可以假設這SIGKILL
也SIGSEGV
與資源限制有關,但這有點牽強。- 看看你可以從
getrusage(RUSAGE_CHILDREN,...)
你的實現中得到什麼,以了解其他的。可能存在特定於作業系統的工具來提供幫助(可能是
ptrace
在 Linux 或 Solaris 上dtrace
),或者可能是調試器類型的技術,但這將與您的特定實現更加相關。(我希望其他人會用一些我完全不知道的魔法來回答。)