为什么 pthread_join 在 306 连接时崩溃(段错误)?

Why does pthread_join crash (seg fault) at 306 Joins?

我正在尝试创建一堆线程,请参阅了解更多有关 pthread 的信息。我复制了一个我找到的程序,它不会创建 1 个线程并加入它,而是创建 X 个线程并加入它们。

当我尝试 100 个线程(MAX_THREAD 100)时,它运行良好。所以我尝试了 1000 个线程,它崩溃了。然后是 500 个线程,它崩溃了。将它加载到 GDB 显示它在 306 个线程时崩溃。然而,这是不一致的。我可以在我正在使用的系统上将它设置为 304,有时它会崩溃,有时它不会。

我将 pthread_create 中的所有 pthread_t 保存在一个数组中,因此我不应该尝试加入同一个线程两次。

段错误发生在这里: 程序收到信号 SIGSEGV,分段错误。 pthread_join 中的 0x004e420e () 来自 /lib/libpthread.so.0

这是我正在使用的代码。

代码:

#define MAX_THREAD 306

#include <pthread.h>
#include <stdio.h>

int something_worked(void) {
    /* thread operation might fail, so here's a silly example */
    void *p = malloc(10);
    free(p);
    return p ? 1 : 0;
}

void *myThread(void *result)
{
   if (something_worked()) {
       *((int*)result) = 42;
       pthread_exit(result);
   } else {
       pthread_exit(0);
   }
}

int main()
{
   pthread_t tid[MAX_THREAD];
   void *status[MAX_THREAD] ;
   int result[MAX_THREAD];
   int i = 0;
   
    for(i = 0; i < MAX_THREAD; i++)
    {
        pthread_create(&tid[i], NULL, myThread, &result[i]);
    }
    for(i = 0; i < MAX_THREAD; i++)
    {
        pthread_join(tid[i], &status[i]);
    }
    
    for(i = 0; i < MAX_THREAD; i++)
    {
        if (status[i] != 0) {
            printf("Thread:[%d] TID[%02x] result %d\n",i, (unsigned)(tid[i]), result[i]);
        } else {
            printf("thread failed\n");
        }
    }

   return 0;
}

我不应该 运行 没话题了:

cat /proc/sys/kernel/threads-max
7470

ulimit 似乎“不错”:

[machine~]$ ulimit -s
10240
[machine~]$ ulimit -v
unlimited

知道为什么我的 pthread_join 崩溃了吗?

I shouldn't be running out of threads:

请注意,这是一个 system-wide 限制,因此如果您有一些其他进程有很多线程 运行,您可能会 运行 线程不足。

在我的 x86_64 系统上,您的程序在 1000 个线程下运行良好。

在 32 位模式下构建时确实失败。那是因为默认的 ulimit -s 是 8MiB,每个线程都继承了这个设置。 8MiB * 307 == 2456MiB,高于 2GiB。

如果您实际上是在 32 位系统上,2GiB 可能是 user-space 进程的内存限制(这取决于您的内核配置方式)。

请注意,失败是由来自 pthread_create 的错误 return 指示的,并且您的程序 没有正确处理 这样的错误 return,这就是它崩溃的原因。

具体来说:

pthread_t tid[MAX_THREAD];  // uninitialized array of tid's
   
for(i = 0; i < MAX_THREAD; i++)
{
    // If this call fails ...
    pthread_create(&tid[i], NULL, myThread, &result[i]);
    // ... then tid[i] is left as "random garbage" ...
}
for(i = 0; i < MAX_THREAD; i++)
{
    // ... which is used here, resulting in the crash.
    pthread_join(tid[i], &status[i]);
}

触摸'。

getconf LONG_BIT
32

所以你指出了代码中的 1 个错误,以及我的假设中的 1 个错误,两者都是正确的!
A: 代码错误没有检查 pthread_create() 的 return 值。
B: 我以为我在一台内存充足的 64 位机器上。

因此我更新了程序以检查 pthread_create() 的 return 值,并将 create/join 循环限制为最后一个“良好”创建。

#define MAX_THREAD 1000
#include <pthread.h>
#include <stdio.h>

int something_worked(void) {
    /* thread operation might fail, so here's a silly example */
    void *p = malloc(10);
    free(p);
    return p ? 1 : 0;
}

void *myThread(void *result)
{
   if (something_worked()) {
       *((int*)result) = 42;
       pthread_exit(result);
   } else {
       pthread_exit(0);
   }
}

int main()
{
   pthread_t tid[MAX_THREAD] = { };
   void *status[MAX_THREAD] = { };
   int result[MAX_THREAD] = { };
   int i = 0;
   int ptc_rtn = 0;
   int max_t = MAX_THREAD;
   
    for(i = 0; i < MAX_THREAD; i++)
    {
        ptc_rtn = pthread_create(&tid[i], NULL, myThread, &result[i]);
        if( ptc_rtn != 0)
        {
            max_t = i;
            break;
        }
    }
    for(i = 0; i < max_t; i++)
    {
        pthread_join(tid[i], &status[i]);
    }
    
    for(i = 0; i < max_t; i++)
    {
        if (status[i] != 0) {
            printf("Thread:[%d] TID[%02x] result %d\n",i, (unsigned)(tid[i]), result[i]);
        } else {
            printf("thread failed\n");
        }
    }

   return 0;
}

程序现在不会出现段错误,并且始终 returns 在 302 和 304 pthread_creates 之间,具体取决于当前可用的内存。

感谢您发现我的错误,并解释错误发生的原因!