1

I am trying to debug some code regarding stack usage. I have made the following test program (just as an example to figure out how the pthread library works):

#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdio.h>

static void *threadFunc1(void *arg)
{
    char arr[5000];
    printf("Hello fromt threadFunc1 address of arr:%p\n", &arr);
    return;
}

static void *threadFunc2(void *arg)
{
    char arr[10000];
    printf("Hello fromt threadFunc2 adress of arr:%p\n", &arr);
    return;
}

int main(int argc, char *argv[])
{
   pthread_t t1,t2;
   pthread_attr_t thread_attr;
   void *res;
   int s;
   size_t tmp_size=0;
   s=pthread_attr_init(&thread_attr);
   assert(s==0);
   s=pthread_attr_setstacksize(&thread_attr , PTHREAD_STACK_MIN );
   assert(s==0);
   s=pthread_attr_getstacksize(&thread_attr , &tmp_size );
   assert(s==0);
   printf("forced stack size of pthread is:%zd\n", tmp_size);
   printf("sizeof char is %zd\n", sizeof(char));

   s = pthread_create(&t1, &thread_attr, threadFunc1, NULL);
   assert(s==0);
   sleep(1);
   s = pthread_create(&t2, &thread_attr, threadFunc2, NULL);
   assert(s==0);
   sleep(1);

   printf("Main done()\n");
   exit(0);
}

When I execute it I get the following output (on my x86_64 Ubuntu):

forced stack size of pthread is:16384
sizeof char is 1
Hello fromt threadFunc1 address of arr:0x7fef350d3b50
Segmentation fault (core dumped)

Is there a way to know how much is left of the requested PTHREAD_STACK_MIN when I enter my newly created thread? If I change the size of the char array when I enter the thread function it seems like the limit is somewhen between 7000 to 8000 which is not what I expected (somewhere in the near of 16384).

kungjohan
  • 475
  • 4
  • 18

1 Answers1

1

There are not a lot of "good" things that can come from playing around with thread stack sizes. Usually when this sort of thing comes up, it's because someone is trying to do create hundreds (or thousands) of threads and running into per process limits. This is generally not a good way to use threads. Example: creating a new thread for every incoming connection request to a server.

Even if that's not why you are asking, a few things you should know.

In production (real world) code, not a simple example, you can't ever be sure that a specific "reduced" stack size per thread is 100% safe. You can test it extensively at a given stack size and then maybe once you're convinced in your own test environment that it's "large enough", probably increase it slightly (maybe 10-15%) for production use. I don't know of any specific tools that can tell you the peak stack usage per thread at run time. Better off to avoid this completely.

Reducing the stack size per thread will not reduce memory consumption directly, or improve performance. You're not optimizing your code by experimenting with this.

It's much safer to use the default stack size chosen by the local implementation when you can, until you have a real reason to change it.

You were missing some header files for prototypes, had missing return values in the thread funcs, etc. plus some other slight cleanups.

Slightly modified version of your code that runs here:

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <limits.h>

static void *threadFunc1(void *arg)
{
    char arr[5000];
    printf("Hello fromt threadFunc1\n");
    return NULL;
}

static void *threadFunc2(void *arg)
{
    char arr[10000];
    printf("Hello fromt threadFunc2\n");
    return NULL;
}

int main(int argc, char *argv[])
{
   pthread_t t1,t2;
   pthread_attr_t thread_attr;
   int s = 0;
   size_t tmp_size=0;

   s = pthread_attr_init(&thread_attr);
   assert(s==0);

   s = pthread_attr_setstacksize(&thread_attr , PTHREAD_STACK_MIN + 0x1000);
   assert(s==0);

   s = pthread_attr_getstacksize(&thread_attr , &tmp_size );
   assert(s==0);

   printf("forced stack size of pthread is:%zu\n", tmp_size);

   s = pthread_create(&t1, &thread_attr, threadFunc1, NULL);
   assert(s==0);

   sleep(1);    /* not the "right" way, but ok for a quick test */

   s = pthread_create(&t2, &thread_attr, threadFunc2, NULL);
   assert(s==0);

   sleep(1);

   printf("Main done()\n");
   return 0;
}

Note: I used

$ gcc -O0 -Wall stack_t.c -o stack_t -pthread
./stack_t

If you want to experiment with other sizes for the stack, be aware that some implementations require the stacksize to be a multiple of the system page file size. You can try values larger than PTHREAD_STACK_MIN as well obviously, just be aware of that potential issue.

EDIT: The example above adds a value to the minimum as an example of increasing it slightly. You may need to add even more. If 0x1000 is not enough, try 0x2000, 0x3000, etc. until you find one that works. As you have discovered, reducing the thread stack size is tricky and can be platform dependent as well. Which is why I have warnings above about it being unsafe.

Randy Howard
  • 2,165
  • 16
  • 26
  • I am not intrested in running some specific amount of threads or limit memory usage. I was just curious if I could reduce default stack size of thread to see if my code overrunned it. The code I wanted to run is not run on linux at all in my production environment so that is the reason to provide a simple example as an illustration. – kungjohan Mar 12 '13 at 20:01
  • If I understand you correctly, you want to reduce the thread stack size, just to find out when it will "break"? That can vary depending upon the code, data sets, etc. About the best you can do is to experiment with reduced stack sizes, and run a lot of test cases with varying data sets, command line arguments, user interactions, etc. (depending upon what the real program does) and find what breaks. This is why the default stack sizes are usually set pretty high in most implementations, to avoid having to go through this process. – Randy Howard Mar 12 '13 at 20:05
  • Yes this is for debugging of code that will run on another platform with limited memory. I know exactly what test cases I want to run, but I dont know how to set the exact stack size I want to test. – kungjohan Mar 13 '13 at 06:58
  • See Edit above, I think the main issue was some issues with your example code. – Randy Howard Mar 13 '13 at 07:13
  • Do you know what happens when you use -O2 to gcc? It optimizes away the stack variables that are not used. You can verify this either by looking at the assembly generated or by running the code in gdb and try to look at the adress of your stack variables. – kungjohan Mar 13 '13 at 21:09
  • Yes. Your system may crash with -O0, depending upon that value of PTHREAD_STACK_MIN there. You will need to adjust up from the PTHREAD_STACK_MIN value in the call to pthread_attr_setstacksize(). You'll have to play with the amount to find something that works in the test fixture, and a different most likely in production code. – Randy Howard Mar 13 '13 at 21:25
  • I have altered the code so that it does not optimize away my allocation. However I don't think your submission answers my original question "Is there a way to know how much is left of the requested PTHREAD_STACK_MIN when I enter my newly created thread?" – kungjohan Mar 14 '13 at 07:14
  • The -O0 takes care of that, but touching the array contents is a better method. The altered code was meant as an example of how to adjust the stack size. The written answer explains there not being a method for knowing exactly how much you need in real world problems. I've spent a lot of time on this, I think I have answered the question. The problem is you don't like the answer. Seems a bit ungrateful from where I'm sitting, after running it on multiple platforms, reproducing your problem, and telling you how to approach tweaking the stack size. Seems pointless for me to continue. – Randy Howard Mar 14 '13 at 13:25