【问题标题】:bash error code 137 vs 1 when out of memory内存不足时的bash错误代码137 vs 1
【发布时间】:2015-06-21 18:11:51
【问题描述】:

上下文

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

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

Stress.exe 是一个 C# 应用程序。

会发生什么

在某一时刻,系统内存不足,这是需要的。返回错误代码。

返回错误代码(echo $?)

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

代码 137 : 当内存过载时被操作系统杀死。

问题

为什么有时操作系统会杀死我的应用程序?为什么结果并不总是一样?

【问题讨论】:

  • 你在使用 Linux 吗?
  • 是的!我虽然 bash 总是 linux?
  • ^^ 不,cygwin...

标签: c# bash mono


【解决方案1】:

假设:

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

让我们谈谈 SGEN,所以当你分配对象时,它们是在 Nursery 中创建的,当你在 Nursery 中耗尽内存时,当 GC 进行扫描并且必须在 Nursery 已满时进行收集时,活对象被移动到它的主要堆。如果主磁头已满,则需要更多的操作系统内存。您可以调整分配给单声道应用程序的初始内存量,甚至可以修复 Sgen 可以使用的内存量(最大值)。超过 8000 字节的托管对象也由 Sgen 的大型对象空间管理器处理,这是非基于 Nursery/major-heap 的内存,但它仍然是托管对象/内存。

因此,通常当 mono 需要更多空间用于托管对象并且操作系统请求额外的块并且操作系统说 NO 时,您会看到 OutOfMemory 异常和您的 0 退出代码。您的压力测试很满意。

但是 OOM 正在观察该单声道进程,并将其分数 (oom_score) 调整得越来越高。它可能随时打击该单声道进程,但我认为它在 GC 扫描时是正确的,此时应用程序线程被 SGEN 挂起,但在 SGEN 由于托管不足而实际执行操作系统内存请求之前幼儿园的记忆空间。因此,您会得到 137. 137 & 127 = 9 的退出,因此单声道进程收到了 SIGKILL 信号(kill -9)并且您的压力测试不满意。

试试这个作为实验:

  • 1) 如果您完全关闭 OOM 杀手。假设这不是一个 您正在强调的现场制作框;-) 您应该会看到 “System.OutOfMemoryException”100% 的时间。
  • 或 2) 设置 oom_adj 只是单声道进程到 -17,OOM 将不理会它。只是 将你的单声道启动包装在一个 shell 脚本中以获取它的 pid 和 echo -17 到那个进程的oom_adj。
  • 或 3) 如果您将单声道进程的 oom_adj 调整得更低(一直向下到 -16,那么您将看到单声道“更多时间”捕获它自己的托管内存中断,但它永远不会是 100%时间......

这根本不是 Mono 和/或 Sgen/GC 相关的“问题”。任何消耗越来越多内存的进程都会被 OOM 杀死。无论是大型的 Oracle 数据库,还是只是存在内存泄漏的应用程序/守护程序等。它们都可能会被杀死。

【讨论】:

  • 谢谢!!真的很清楚为什么会发生,而且你的预测确实是正确的!
  • 太棒了!很高兴我能帮上忙。
【解决方案2】:

“本文描述了 Linux 内存不足 (OOM) 杀手以及如何找出它为什么会杀死特定进程。它还提供了配置 OOM 杀手以更好地适应许多不同环境的需求的方法。”

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

【讨论】:

  • 非常感谢!真的很有用。但是我不明白这篇文章为什么有时一个人先于另一个人行动?
猜你喜欢
  • 1970-01-01
  • 2021-10-05
  • 1970-01-01
  • 2017-08-27
  • 1970-01-01
  • 2020-12-31
  • 1970-01-01
  • 2015-09-20
相关资源
最近更新 更多