Python中os.fork OSError: [Errno 12] 无法分配内存(但内存不是问题)

13
我遇到了类似的问题:Python subprocess.Popen "OSError: [Errno 12] Cannot allocate memory" 我有一个守护进程,运行良好几分钟后,就无法通过popen2.Popen3()运行shell程序。它生成20个线程。内存似乎不是问题;该机器上只有这个程序在运行,具有2G的RAM,并且只使用不到400M的内存。我一直在记录ru_maxrss,这仅为50M(在引发OSError之前和之后)。
ulimit -a:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15962
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15962
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

我一直在观察运行时的 free -mls /proc/$pid/fd | wc -l,但是它们都没有显示出资源耗尽的情况。下面是运行时典型的 free -m 输出:

             total       used       free     shared    buffers     cached
Mem:          2003        374       1628          0         46        154
-/+ buffers/cache:        173       1830
Swap:          283          0        283

...并且fd计数约为90-100。

主机是Ubuntu 12.04(服务器jeos-最小vm),Python 2.7.3,运行在VMWare主机上。

因此,我想知道:下一步该怎么诊断失败的原因?是否有更多的资源统计信息可以收集?我需要降到strace的级别吗?


4
尝试使用 strace -ff 命令来运行您的进程。这将告诉您哪个系统调用失败并可能提供有用的提示,帮助您找出问题所在。 - Andrea Corbellini
如果底层问题实际上与链接的问题相同,则添加与RAM大小相当的交换是可接受的解决方法。这也可以用作链接的已接受答案中假设的简单测试。重新阐述问题,Popen == fork + exec,其中fork在极短的时间内[可能几乎]使使用的内存翻倍。内核可能会告诉你去死... - Dima Tisnek
我建议使用http://sscce.org/进行演示您的问题。 - dstromberg
如果你因为整数下溢而意外尝试分配2 ** 64-2的内存,那么你会得到ENOMEM。对于strace,请点赞+1。 - myaut
你真的不应该再使用os.popen(),特别是在2.7+版本中。请参考https://docs.python.org/2/library/os.html#file-object-creation并使用subprocess。 - cgseller
显示剩余5条评论
2个回答

2
假设:如果您的虚拟机是32位的,可能会用完地址空间。
不是内存:而是地址空间。让我解释一下:在Linux中,许多东西(IO、显卡、内存映射文件)使用地址空间,而不一定消耗相应数量的主内存。
以下是相关问题的解释:

http://us.download.nvidia.com/XFree86/Linux-x86/331.89/README/knownissues.html

在X86平台上寻找“Kernel virtual address space exhaustion”部分,使用dmesg测试是否出现这种情况。 mmapENOMEM错误很可能意味着“地址空间不足”的情况,而不仅仅是“内存不足”,尽管我不确定如何在CPython中诊断此问题。 如果您的系统上有任何进程运行并将一些大文件mmap,那么就会出现这种情况。

1

检查您的磁盘驱动器是否已满,这在我的情况下是问题所在。

bravo@by1-dotbravo-01:~$ df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda1              16G   16G     0 100% /
tmpfs                 2.0G     0  2.0G   0% /dev/shm
/dev/sdb              296G  162G  119G  58% /home

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接