出于测试目的强制 `pthread_create` 失败

问题描述 投票:0回答:2

为了测试错误恢复,我想让

pthread_create
以可预测的方式失败。最明显的方法是对特定进程中允许存在的线程数设置硬性上限。

特别是在 Linux 上,

setrlimit(RLIMIT_NPROC)
会影响进程和线程的创建;将限制设置为 1 将导致
pthread_create
setrlimit
调用之后的任何代码都失败。 Solaris 衍生的 Unixes [我只测试了 OmniOS r151030] 没有 RLIMIT_NPROC,但确实有办法通过更精美的
setrctl
接口来限制进程中的线程数量。

在我尝试过的任何其他 Unix 上,我都无法找到从 C 语言执行此操作的方法。特别是,这个问题底部的测试程序将在所有(AIX 7.1、FreeBSD 12.1、NetBSD 9.3、OpenBSD 6.8)上打印“fail: pthread_create successed”。

所以,问题是:请修改测试程序,使

pthread_create
调用在一个或多个既不是 Linux 也不是 Solaris 的 Unix 上失败。首选适用于“多种”Unix 的答案(例如,如果您可以展示一种在“所有”BSD 派生系统上执行此操作的方法,那就太好了)。 注意:除了实际执行测试程序的进程之外,会对其他进程产生副作用的答案(例如,对特定 uid 或整个系统下运行的线程总数施加限制)对我来说没有好处。

#include <pthread.h> #include <stdio.h> #include <string.h> #include <sys/resource.h> static void *threadproc(void *arg) { puts("fail: pthread_create succeeded"); return arg; } int main(void) { struct rlimit r = { 1, 1 }; if (setrlimit(RLIMIT_NPROC, &r)) { perror("error: setrlimit failed"); return 1; } pthread_t t; int err = pthread_create(&t, 0, threadproc, 0); if (err) { printf("ok: pthread_create failed (%s)\n", strerror(err)); return 0; } err = pthread_join(t, 0); if (err) printf("error: pthread_join failed (%s)\n", strerror(err)); return 1; }


AIX
c testing unix pthreads posix
2个回答
1
投票

AIX setrlimit()

RLIMIT_THREADS

:
RLIMIT_THREADS

每个进程可以创建的最大线程数。此限制由内核和 pthread 调试库强制执行。

只需更换

setrlimit(RLIMIT_NPROC, &r)

setrlimit(RLIMIT_THREADS, &r)

(但是,我无法访问 AIX 实例进行测试)

BSD

BSD 似乎没有任何不依赖于每个用户或整个系统限制的等价物。

您可以使用 POSIX 函数保护堆栈内存

int mprotect(void *addr, size_t len, int prot);

0
投票

类似这样的:

   pthread_attr_t attr;
    // attr initialization here:
   int rc; 
   void  *mystack;
   size_t mystacksize = 2 * PTHREAD_STACK_MIN;
                                                                                
   if (pthread_attr_init(&attr) < -1) {                                        
      perror("error in pthread_attr_init");                                     
      return -1;
   }                                                                            
                                                                                
   // Get a big enough stack and align it on 4K boundary.
   mystack = malloc(PTHREAD_STACK_MIN * 3);
   if (!mystack) {
      perror("Unable to acquire storage.");
      return -1;
   }
   // Align stack, memory leak is possible
   mystack =  (((intptr_t)mystack) & 0xfff)
               ? (void*)( ( ((intptr_t)mystack) & 0xfff) + 0x1000): mystack;
                                                                                
    rc = pthread_attr_setstack(&attr, mystack, mystacksize);
    if (rc != 0) {                                           
        perror("pthread_attr_setstack()");
        return -1;
    } 

    // Protect stack memory:
    rc = memprotect(stack, mystacksize, PROT_NONE);
    if (rc) {
        perror("mprotect()");
        return -1;
    }

    pthread_t t;
    // Should fail, cause stack memory is protected
    int err = pthread_create(&t, attr, threadproc, 0);
    if (err) {
        printf("ok: pthread_create failed (%s)\n", strerror(err));
        return 0;
    }

© www.soinside.com 2019 - 2024. All rights reserved.