bash 内存不足时错误代码 137 与 1

bash error code 137 vs 1 when out of memory

上下文

我 运行 linux bash 中的以下命令:

mono --debug --debugger-agent=transport=dt_socket,address=198.178.155.198:10000 ./Stress.exe

Stress.exe 是 C# 应用程序。

会发生什么

有一次系统内存不足,这是需要的。返回错误代码。

返回错误码(echo $?)

代码 1:当我的程序因为内存不足而创建抛出时。

代码 137 : 内存过载时被 OS 杀死。

问题

为什么有时 OS 会终止我的应用程序?为什么结果不总是一样?

"This article describes the Linux out-of-memory (OOM) killer and how to find out why it killed a particular process. It also provides methods for configuring the OOM killer to better suit the needs of many different environments."

http://www.oracle.com/technetwork/articles/servers-storage-dev/oom-killer-1911807.html

假设:

  • Mono 正在 运行基于 SGEN 的 GC
  • Linux OOM Killer 已实际启用
  • 您的 Stress.exe 仅分配托管内存,即没有本机互操作,没有使用 Marshaling 内存分配器,没有标记为不安全的代码等。
  • 您一直在创建对象,但从不释放这些引用。

让我们谈谈 SGEN,当您分配对象时,它们是在托儿所中创建的,当您 运行 托儿所内存不足时,当 GC 进行扫描并且必须执行托儿所收集时它已满,活动对象将移至其主要堆。如果主头已满,则需要更多 OS 内存。您可以调整分配给单声道应用程序的初始内存量,甚至可以固定 Sgen 可以使用的内存量(最大)。超过 8000 字节的托管对象也由 Sgen 的大对象 Space 管理器处理,这是基于 non-nursery/major-heap 的内存,但它仍然被管理 objects/memory.

所以通常当 mono 需要更多 space 用于托管对象并执行 OS 请求额外的块并且 OS 说不时,您会看到 OutOfMemory 异常和您的 0退出代码。您的压力测试很满意。

但 OOM 正在观察单声道进程并将其分数 (oom_score) 调整得越来越高。它可能会在任何时候触发该单进程,但我认为当应用程序线程被 SGEN 挂起但在 SGEN 实际执行 OS 内存请求之前,它是正确的托儿所中的托管内存 space 不足。因此你得到 137 的出口。137 & 127 = 9,所以单声道进程被发送了一个 SIGKILL 信号(kill -9)并且你的压力测试不快乐。

试试这个作为实验:

  • 1) 如果完全关闭OOM killer。假设这不是一个 您正在强调的现场制作框 ;-) 您应该会看到 "System.OutOfMemoryException" 100% 的时间。
  • 或 2) 设置 oom_adj 只有单声道过程到 -17,OOM 将不理会它。只是 将单声道启动包装在 shell 脚本中以获取它的 pid 和 echo -17 到该进程的 oom_adj。
  • 或 3) 如果你将单声道进程的 oom_adj 调低(一直调到 -16,你会看到单声道捕获它自己的托管内存中断 'more of the time' 但它会永远不要 100% 的时候....

这根本不是 Mono and/or Sgen/GC 相关的 'issue'。任何消耗越来越多内存的进程都可能被 OOM 终止。无论是一个庞大的 Oracle 数据库,还是只是一个有内存泄漏的 app/daemon,等等。它们都会被杀死。