如何检查,超过了哪个限制?(由于ulimit终止了进程。)


11

假设进程在有限的环境中运行:

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

程序终止。

可能有很多原因:超出了内存/时间/文件限制;只是简单的段错; 甚至正常终止,返回码为0。

如何在不修改程序的情况下检查程序终止的原因?

PS我的意思是“当给定二进制文件时”。也许一些包装器(ptrace-ing等)可能会有所帮助?

Answers:


6

一般来说,我认为您不能不幸。(某些操作系统可能会为此提供支持,但是我不知道我所知道的支持此功能的。)

有关资源限制的参考文档:getrlimit来自POSIX 2008。

以CPU限制为例RLIMIT_CPU

  • 如果该过程超出了软限制,则会发送 SIGXCPU
  • 如果该过程超出了硬限制,它将变得很简单 SIGKILL

如果可以wait()在程序上执行,则可以确定该程序是否已被杀死SIGXCPU。但是您无法区分SIGKILL因违反硬限制而派遣的派遣人员与外部的普通老杀手。而且,如果程序处理XCPU,您甚至不会从外部看到它。

同样的事情RLIMIT_FSIZE。如果程序不处理,则可以SIGXFSZwait()状态中看到。但是一旦超出文件大小限制,唯一发生的事情就是将再次收到尝试再次测试该限制的I / O,EFBIG这将由程序内部处理(或不幸的是,不会)。如果程序处理SIGXFSZ,则与上述相同-您将不会知道。

RLIMIT_NOFILE?好吧,您甚至都没有收到信号。open和朋友只需返回EMFILE该程序。它不会以其他方式困扰,因此在这种情况下,无论采用哪种编码方式,它都会失败(或不会失败)。

RLIMIT_STACK?好老SIGSEGV,无法与其他原因得分相提并论。(您将从状态中得知这是杀死进程的原因wait。)

RLIMIT_AS并且RLIMIT_DATA只会使malloc()其他一些失败(或者SIGSEGV在尝试扩展Linux上的堆栈时达到了AS限制时接收失败)。除非程序编写得非常好,否则在那时可能会相当随机地失败。

简而言之,总的来说,这些失败与其他进程死因没有明显的不同,因此您不能确定,或者可以完全由程序处理,在这种情况下,它决定是否/何时/如何进行,而不是您从外部。

据我所知,您能做的最好的事情就是编写一些代码,将其分叉到您的程序中,然后等待,然后:

  • 检查退出状态以进行检测SIGXCPUSIGXFSZ(AFAIK,这些信号仅在操作系统出现资源限制问题时才产生)。根据您的确切需求,您可以假设SIGKILLSIGSEGV也与资源限制有关,但这有点麻烦。
  • 查看您可以从getrusage(RUSAGE_CHILDREN,...)实现中获得什么,以获取有关其他实现的提示。

可能存在特定于OS的工具来帮助您(可能ptrace在Linux或Solaris上类似dtrace),或者可能是调试器类型的技术,但这将与您的特定实现更加紧密地联系在一起。


(我希望其他人会回答一些我完全不知道的不可思议的事情。)


好。那(Mem)超出内存限制,(Time)时间限制,(Err)其他错误这三个呢?我知道做包装器,malloc但是不幸的是,它通常不能解决内存问题,因为总的来说,它与系统调用有关brk(我对吗?)。
2011年

1
如果不控制程序,包装malloc将无济于事。如果你在谈论黑客像LD_PRELOAD荷兰国际集团说的界线为贵“不修改的过程中”约束,它会有点帮助,但不是真的- ,,malloc 并且将失败,完全一样,如果你真的是在内存不足的情况(但远低于内存限制)。时限为,我不知道挂钟的时限。brksbrkmmapENOMEMRLIMIT_CPU

感谢您向我保证brk。如我所见,由于waitpid,要求“程序未处理信号X,Y,Z ...”将解决SIGXCPU,SIGXFSZ,SIGSEGV的问题(如果我错了,请纠正我)。
2011年

1
SIGSEGV可以在不违反资源限制的情况下引发(空指针取消引用是引发该异常的最常见的情况)-您不能确定它的ulimit导致它。

感谢您向我保证brk。如我所见,由于waitpid,要求“程序未处理信号X,Y,Z ...”将解决SIGXCPU,SIGXFSZ,SIGSEGV的问题。我对吗?
2011年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.