java - 哪些非 ulimit 限制会导致 open 在 Linux 上返回 EMFILE?

标签 java linux scala ulimit

在使用 JVM 运行 scala 编译器时,我注意到,如果同时生成足够的 (8) 个 JVM 实例,某些 JVM 将退出并带有 EMFILE。按顺序运行时,这些调用都会成功。我还对这些作业进行了 strace,发现当 open() 因 EMFILE 失败时,它们只打开了 1024 个文件描述符中的 64 个。这也对应于我在运行时检查/proc/xyz/fd 时看到的内容。

我在文档中可以找到的 EMFILE 的唯一原因是 rlimit 'NOFILE' 太低。但是,软限制设置为 1024(硬限制为 1048576)。即使将 8 次调用的所有文件描述符加起来,8*64 < 1024。此外,我的理解(通过一个小型 C 测试程序确认)rlimit 应该独立应用于进程。

JVM 是高度多线程的(如果这在某种程度上相关的话)。 该进程正在从本地连接的 PV 的 ext4 LV 运行。操作系统是 Ubuntu 16.04,尽管我在 RHEL8 上也遇到过类似的故障。该系统有 128GiB RAM,并且没有其他竞争进程。

此外,奇怪的是,如果我在启 Action 业的 shell 脚本中将软 ulimit 增加到 102400,8 个并发作业将成功完成。

还有哪些条件可以导致内核返回 EMFILE 进行打开?

作为引用,以下是失败时打开/关闭调用的跟踪:

11665 open("<real filename censored for stackoverflow>", O_RDONLY) = 63
12659 open("/sys/fs/cgroup/memory/user.slice/memory.limit_in_bytes", O_RDONLY) = 64
11665 open("<real filename censored for stackoverflow>", O_RDONLY <unfinished ...>
12659 close(64)                         = 0
11665 <... open resumed> )              = -1 EMFILE (Too many open files)
12659 open("/sys/fs/cgroup/memory/user.slice/memory.stat", O_RDONLY) = 64
12659 close(64)                         = 0
11790 open("/sys/fs/cgroup/memory/user.slice/memory.limit_in_bytes", O_RDONLY <unfinished ...>
12658 open("/sys/fs/cgroup/memory/user.slice/memory.limit_in_bytes", O_RDONLY <unfinished ...>
11796 open("/sys/fs/cgroup/memory/user.slice/memory.limit_in_bytes", O_RDONLY <unfinished ...>
12658 <... open resumed> )              = 65
11796 <... open resumed> )              = 66

我刚刚了解到 JVM 正在自行操作 ulimit!它在启动时立即最大化软限制:

3059  getrlimit(RLIMIT_NOFILE, {rlim_cur=1024, rlim_max=1024*1024}) = 0
3059  setrlimit(RLIMIT_NOFILE, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0

我还是没明白为什么会出现这种情况。我暂时放弃了。只是将其限制为一次最多 6 个构建。

最佳答案

我发现了问题所在。所有 JVM 实例都在共享 FUSE 文件系统上运行。 FUSE 守护进程耗尽了描述符,并将该错误报告给在其上运行的 JVM。

关于java - 哪些非 ulimit 限制会导致 open 在 Linux 上返回 EMFILE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69493390/

相关文章:

java - 如何拆分字符串,包括标点符号?

java - JPanel 不会调整大小

java - 在java中的Clip对象上添加sfx

c - 使用 fork 两次 - 奇怪的行为

scala - 查找两种 Scala 类型的最大公共(public)子类型

java - 将流转换为字符串 block ,反之亦然

java - 编写一个接受数组并仅返回正数的函数

c - 我如何覆盖加载了 dlopen 的库中的全局符号?

内核版本

scala insert to redis 给出任务不可序列化