直接看/proc/[pid]/limits的max processes行(soft列),对比ps -t -p [pid] | wc -l,若当前线程数≥软限制值即为线程数超限;注意systemd、docker、pam等可能覆盖ulimit -u设置。

pthread_create 返回 EAGAIN 怎么快速确认是线程数超限
直接看 /proc/[pid]/limits 里的 Max processes 行,它就是当前进程能创建的线程总数(含主线程)。pthread_create 返回 EAGAIN 或 std::thread 构造抛 resource_unavailable_try_again,90% 是这个值被踩到了。
别信 ulimit -u 输出就一定准——systemd 服务、容器、PAM 配置都可能覆盖它。验证方法:
- 用
ps -T -p [pid] | wc -l数出当前线程数 - 对比
cat /proc/[pid]/limits | grep "Max processes"的软限制值(Soft列) - 如果前者 ≥ 后者,就是它卡死了
为什么改了 ulimit -u 还没用
因为很多环境根本不读 shell 的 ulimit 设置:
- systemd 服务:必须在
.service文件的[Service]段加LimitNPROC=65535,或全局设DefaultLimitNPROC=65535在/etc/systemd/system.conf - Docker 容器:得用
--ulimit nproc=65535:65535启动,K8s 要配securityContext.limits.nproc - RHEL/CentOS:可能启用了
user.max_processes这类 PAM 限制,ulimit看不见,得查/etc/security/limits.d/和/etc/pam.d/common-session
临时测试可用 prlimit --nproc=65535 --pid [pid] 直接重设运行中进程的限制,不用重启。
在无 root/sudo 权限的环境(云容器、VPS、隔离主机)中安装并配置 OpenClaw 浏览器工具的 headless Chrome。适用场景:...
栈大小和 threads-max 也得一起看
线程数不是光调 nproc 就完事。每个线程默认占 8MB 栈空间(ulimit -s 输出单位是 KB),内存不够也会让 pthread_create 失败,有时还伪装成 EAGAIN。
- 查当前栈限制:
ulimit -s,若为 8192 就是 8MB - 减小栈可临时多撑点线程:
ulimit -s 2048(2MB),但注意递归深度和局部变量大小 - 系统级总线程上限:
cat /proc/sys/kernel/threads-max,如果ps -eLf | wc -l接近它,就得调这个,不是ulimit - 别忘了
pid_max:cat /proc/sys/kernel/pid_max,它管 PID 分配池,超了会报fork: Cannot allocate memory,和线程失败现象高度相似
std::thread 创建失败时怎么避免悬空引用
别用 detach() 应对线程数限制问题——它不解决资源竞争,反而容易因捕获栈变量导致崩溃。线程池里更稳妥的做法是:
- 用
std::vector<:thread></:thread>存活线程句柄,配合std::atomic<int></int>计数控制并发数 - submit 任务前先
cv.wait(lock, []{ return active_threads.load() - 线程函数结束时
active_threads--并notify_one() - 避免把
std::thread对象放在栈上然后detach(),尤其别在线程里访问已销毁的 lambda 捕获对象
真正卡住的从来不是语法,而是 /proc/[pid]/limits 里那个安静躺着的 Max processes 值,以及它背后被 systemd、cgroup、PAM 层层覆盖的真实来源。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










