【问题标题】:Python script terminated by SIGKILL rather than throwing MemoryErrorPython 脚本被 SIGKILL 终止而不是抛出 MemoryError
【发布时间】:2014-09-19 22:48:57
【问题描述】:

再次更新

我尝试创建一些简单的方法来重现此问题,但没有成功。

到目前为止,我已经尝试了各种简单的数组分配和操作,但它们都抛出 MemoryError 而不仅仅是 SIGKILL 崩溃。

例如:

x =np.asarray(range(999999999))

或:

x = np.empty([100,100,100,100,7])

按照它们应该的方式抛出 MemoryErrors。

我希望在某个时候有一种简单的方法来重新创建它。

结束更新

我有一个运行 numpy/scipy 和一些自定义 C 扩展的 python 脚本。

在我的 Ubuntu 14.04 下的 Virtual Box 上,它可以正常运行。

在 Amazon EC2 T2 微型实例上,它会终止(运行一段时间后)并输出:

被杀

在python调试器下运行,信号未被捕获,调试器也退出。

在 strace 下运行,我得到:

munmap(0x7fa5b7fa6000, 67112960)        = 0
mmap(NULL, 67112960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5b7fa6000    
mmap(NULL, 67112960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5affa4000    
mmap(NULL, 67112960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5abfa3000    
mmap(NULL, 67637248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5a7f22000    
mmap(NULL, 67637248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa5a3ea1000    
mmap(NULL, 67637248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa59fe20000    
gettimeofday({1406518336, 306209}, NULL) = 0    
gettimeofday({1406518336, 580022}, NULL) = 0    
+++ killed by SIGKILL +++

在尝试捕获“SIGKILL”时在 gdb 下运行,我得到:

[Thread 0x7fffe7148700 (LWP 28022) exited]

Program terminated with signal SIGKILL, Killed.
The program no longer exists.
(gdb) where
No stack.

运行python的跟踪模块(python -m trace --trace),我得到:

defmatrix.py(292):         if (isinstance(obj, matrix) and obj._getitem): return
defmatrix.py(293):         ndim = self.ndim
defmatrix.py(294):         if (ndim == 2):
defmatrix.py(295):             return
defmatrix.py(336):         return out
 --- modulename: linalg, funcname: norm
linalg.py(2052):     x = asarray(x)
 --- modulename: numeric, funcname: asarray
numeric.py(460):     return array(a, dtype, copy=False, order=order)

目前我想不出其他任何事情来弄清楚发生了什么。

我怀疑它可能内存不足(它是一个 AWS Micro 实例),但我不知道如何确认或否认这一点。

我可以使用其他工具来帮助准确定位程序停止的位置吗? (或者我正在以错误的方式运行上述工具之一来解决这个问题?)

更新

Amazon EC2 T2 微实例默认没有定义交换空间,所以我添加了一个 4GB 的交换文件,并且能够运行程序完成。

但是,我仍然对一种运行程序的方式非常感兴趣,它会以一些更接近“内存不足”而不是“已杀死”的消息而终止

如果有人有任何建议,他们将不胜感激。

【问题讨论】:

    标签: python-2.7 gdb out-of-memory sigkill


    【解决方案1】:

    听起来您遇到了可怕的 Linux OOM Killer。当系统完全耗尽内存并且内核绝对需要分配内存时,它会杀死一个进程而不是使整个系统崩溃。

    查看系统日志以确认这一点。一行类似于:

    kernel: [884145.344240] mysqld invoked oom-killer:
    

    后来又跟着:

    kernel: [884145.344399] Out of memory: Kill process 3318
    

    应该存在(在这个例子中,它特别提到了mysql)

    您可以将这些行添加到您的 /etc/sysctl.conf 文件中以有效禁用 OOM 杀手:

    vm.overcommit_memory = 2
    vm.overcommit_ratio = 100
    

    然后重启。现在,原始的、需要大量内存的进程应该无法分配内存,并希望抛出正确的异常。

    设置overcommit_memory 意味着Linux 不会过度提交内存,这意味着如果内存不足,内存分配将失败。有关overcommit_ratio 有什么影响的详细信息,请参阅此答案:https://serverfault.com/a/510857

    【讨论】:

    • 太棒了。这正是它。我找不到一种简单的方法来重现这一点,但这正是正在发生的事情。对此的确认在系统日志中。开头:内核:[884145.344240] mysqld 调用了oom-killer:并以:内核:[884145.344399] 内存不足:终止进程 3318
    • 按照上述过程,不知从何而来的神秘“进程被杀死”消息已被令人愉快的 python 堆栈跟踪和 MemoryError 异常所取代。谢谢!
    • Mac 显然也做了同样的事情。我的syslogMay 25 13:19:50 MacBook-Pro kernel[0] <Notice>: low swap: killing pid 33578 (Python)。克。
    猜你喜欢
    • 2010-10-15
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多