OSError: [Errno 24] No file descriptors available
创建多处理队列时。仅当使用高山图像 (FROM python:alpine3.19
) 普通图像 (FROM python
) 工作正常时才会出现这种情况。我尝试过增加 ulimit。
默认泊坞窗设置:
"default-ulimits": {
"nofile": {
"Hard": 4096,
"Name": "nofile",
"Soft": 4096
},
"nproc": {
"Hard": 4096,
"Name": "nproc",
"Soft": 4096
}
}
也在“运行”命令期间参见下文。 ulimit 设置似乎工作正常(在
/proc/1/limits
中可见)。还有其他我不知道的限制吗?
Dockerfile:
# FROM python
FROM python:alpine3.19
WORKDIR test
COPY . .
CMD [ "python", "test.py"]
测试.py:
import multiprocessing
import time
import subprocess
if __name__ == '__main__':
queues = []
print((subprocess.check_output(['cat', '/proc/1/limits'])).decode())
for i in range(1000):
print(f"Appending multiprocessing.Queue() n. {i} ", end="")
queues.append(multiprocessing.Queue())
print("ok")
time.sleep(0.1)
print("all ok")
(
docker build -t test .
)
FROM python
):
docker run -it --rm --ulimit nofile=128 test
Appending multiprocessing.Queue() n. 62 Traceback (most recent call last):
File "/test/test.py", line 10, in <module>
queues.append(multiprocessing.Queue())
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/multiprocessing/context.py", line 103, in Queue
return Queue(maxsize, ctx=self.get_context())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/multiprocessing/queues.py", line 42, in __init__
self._reader, self._writer = connection.Pipe(duplex=False)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/multiprocessing/connection.py", line 543, in Pipe
fd1, fd2 = os.pipe()
^^^^^^^^^
OSError: [Errno 24] Too many open files
docker run -it --rm --ulimit nofile=4096 test
Appending multiprocessing.Queue() n. 998 ok
Appending multiprocessing.Queue() n. 999 ok
all ok
FROM python:alpine3.19
):docker run -it --rm --ulimit nofile=128 test
Appending multiprocessing.Queue() n. 62 Traceback (most recent call last):
File "/test/test.py", line 10, in <module>
queues.append(multiprocessing.Queue())
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/multiprocessing/context.py", line 103, in Queue
return Queue(maxsize, ctx=self.get_context())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/multiprocessing/queues.py", line 42, in __init__
self._reader, self._writer = connection.Pipe(duplex=False)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/multiprocessing/connection.py", line 543, in Pipe
fd1, fd2 = os.pipe()
^^^^^^^^^
OSError: [Errno 24] No file descriptors available
docker run -it --rm --ulimit nofile=4096 test
Appending multiprocessing.Queue() n. 85 Traceback (most recent call last):
File "/test/test.py", line 10, in <module>
queues.append(multiprocessing.Queue())
^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/multiprocessing/context.py", line 103, in Queue
return Queue(maxsize, ctx=self.get_context())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/multiprocessing/queues.py", line 48, in __init__
self._wlock = ctx.Lock()
^^^^^^^^^^
File "/usr/local/lib/python3.12/multiprocessing/context.py", line 68, in Lock
return Lock(ctx=self.get_context())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/multiprocessing/synchronize.py", line 169, in __init__
SemLock.__init__(self, SEMAPHORE, 1, 1, ctx=ctx)
File "/usr/local/lib/python3.12/multiprocessing/synchronize.py", line 57, in __init__
sl = self._semlock = _multiprocessing.SemLock(
^^^^^^^^^^^^^^^^^^^^^^^^^
OSError: [Errno 24] No file descriptors available
编辑:
这个问题似乎与使用 musl 的 alpine linux 有关,而 debian 使用 glibc:实际上并不是缺少文件描述符,但是如果超过信号量的限制,POSIX-
sem_open
也可以提高EMFILE
。
由于所有列出的多处理类在内部都使用信号量,因此最终会达到此限制(之前对于使用多个信号量的类)。
SEM_NSEMS_MAX
,并指定为 256。实际提高 EMFILE
的代码位于 sem_open
。
非常感谢#musl 的@psykose 向像我这样的 C 新手指出了这一点。
那么为什么它可以在 glibc / debian 上运行呢?
一般来说,
sem_open
的glibc实现不允许发生EMFILE
,因此使用glibc根本不会出现这个问题(当然,除非系统资源耗尽)。一些进一步的信息可以在 libc-help 邮件列表上获得。
虽然我在 musl 邮件列表上发布了有关该问题的信息,但我真的不知道更改需要做多少工作以及优先级是什么。因此,目前最明智的方法可能是使用目前使用 glibc 的不同发行版。