I'm playing around with creating a BUNCH of threads, just see learn a bit more about pthread. I've copied a program I found, and instead of making 1 thread, and joining it, it will create X threads, and join them.
When I tried 100 threads (MAX_THREAD 100), it worked fine. So I tried 1000 threads, and it crashed. Then 500 threads, and it crashed. Loading it into GDB showed it crashed at 306 threads. However, it's inconsistent. I can set it to 304 on the system I'm using, and sometimes it'll crash, sometimes it wont.
I'm keeping all the pthread_t's from the pthread_create in an array, so I shouldn't be trying to join the same thread twice.
The segfault happens here: Program received signal SIGSEGV, Segmentation fault. 0x004e420e in pthread_join () from /lib/libpthread.so.0
Here's the code I'm using.
Code:
#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;
}
I shouldn't be running out of threads:
cat /proc/sys/kernel/threads-max
7470
ulimit's seem to be "good":
[machine~]$ ulimit -s
10240
[machine~]$ ulimit -v
unlimited
Any idea why my pthread_join crashes?
I shouldn't be running out of threads:
Note that this is a system-wide limit, so you could be running out of threads IF you have some other processes with many threads running.
On my x86_64
system your program runs fine with with 1000 threads.
It does fail when built in 32-bit mode. That is because the default ulimit -s
is 8MiB, and each thread inherits that setting. 8MiB * 307 == 2456MiB, which is above 2GiB.
If you are in fact on a 32-bit system, 2GiB might be the memory limit for user-space processes (this depends on how your kernel was configured).
Note that the failure is signaled by error return from pthread_create
, and your program does not handle such error return correctly, which is why it crashes.
Specifically:
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]);
}