如何让pthread_create在非Linux/Solaris类Unix系统可控失败以测试?
跨Unix系统触发pthread_create失败的通用测试实现
原测试程序依赖RLIMIT_NPROC触发pthread_create失败,但该资源限制在多数非Linux/Solaris系统中仅限制用户级进程总数,而非单个进程的线程数,因此无法生效。以下是适配AIX 7.1、FreeBSD 12.1、NetBSD 9.3、OpenBSD 6.8等系统的通用方案,且不会影响当前进程外的其他进程:
核心思路
- 优先使用系统原生的线程数限制资源(如
RLIMIT_THREADS),直接限制单个进程可创建的线程总数; - 对不支持线程数限制的系统,通过限制进程的虚拟内存或栈空间,让新线程因内存分配失败而无法创建;
- 用条件编译适配不同Unix系统的接口差异,保证代码的可移植性。
修改后的测试代码
#include <pthread.h> #include <stdio.h> #include <string.h> #include <sys/resource.h> #include <unistd.h> static void *threadproc(void *arg) { puts("fail: pthread_create succeeded"); return arg; } int main(void) { int ret = 0; struct rlimit r; // 尝试设置线程数限制(优先适配支持RLIMIT_THREADS的系统) #ifdef RLIMIT_THREADS r.rlim_cur = 1; r.rlim_max = 1; if (setrlimit(RLIMIT_THREADS, &r) == 0) { goto attempt_create; } perror("warning: setrlimit(RLIMIT_THREADS) failed, falling back to stack limit"); #endif // fallback方案:设置极小的栈空间限制,让新线程无法分配栈内存 // 获取系统最小栈限制,确保设置值合法 if (getrlimit(RLIMIT_STACK, &r) == 0) { r.rlim_cur = (r.rlim_min > 4096) ? r.rlim_min : 4096; r.rlim_max = r.rlim_cur; if (setrlimit(RLIMIT_STACK, &r) == 0) { goto attempt_create; } perror("warning: setrlimit(RLIMIT_STACK) failed, falling back to vmem limit"); } // 最终fallback:限制虚拟内存总量 r.rlim_cur = 1024 * 1024; // 1MB r.rlim_max = 1024 * 1024; if (setrlimit(RLIMIT_VMEM, &r) != 0) { perror("error: all setrlimit attempts failed"); return 1; } attempt_create: pthread_t t; int err = pthread_create(&t, NULL, threadproc, NULL); if (err) { printf("ok: pthread_create failed (%s)\n", strerror(err)); ret = 0; } else { err = pthread_join(t, NULL); if (err) { printf("error: pthread_join failed (%s)\n", strerror(err)); } ret = 1; } return ret; }
方案说明
- RLIMIT_THREADS适配:FreeBSD 12+、NetBSD 9+、OpenBSD 6.6+、AIX 7.2+等系统支持该资源限制,直接将单个进程的线程数上限设为1,当前进程已有主线程,后续
pthread_create必然失败; - 栈空间限制:对不支持线程数限制的系统(如AIX 7.1),将栈空间限制设为系统允许的最小值,新线程因无法分配足够栈内存而创建失败;
- 虚拟内存限制:作为最后的兜底方案,限制进程的总虚拟内存,确保新线程无法分配所需内存;
- 所有资源限制仅作用于当前测试进程,不会影响系统内其他进程。
内容的提问来源于stack exchange,提问作者zwol
相关产品推荐
相关产品推荐

