5

I noticed just now that when I spawn a thread using pthread_create(), my request for setting a custom stack size for the thread seems to be ignored. In particular, if I call pthread_attr_getstacksize() from within the spawned thread, it always reports the default stack size, regardless of what I had asked for.

This behavior is seen under both Linux and MacOS/X, so I suspect that I am doing something wrong, but I don't know what it is.

To reproduce the problem, compile and run the code below (via "g++ stack_test.cpp -lpthread ; ./a.out"). It tries a bunch of different stack sizes and complains if its requests aren't honored. The problematic output looks like this:

Jeremys-Mini:~ lcsuser1$ ./a.out 
Testing creation of a thread with stack size:  8192
ThreadFunc:  ERROR, wrong stack size!  (Requested:  8192, got: 524288)
Testing creation of a thread with stack size:  16384
ThreadFunc:  ERROR, wrong stack size!  (Requested:  16384, got: 524288)
Testing creation of a thread with stack size:  24576
ThreadFunc:  ERROR, wrong stack size!  (Requested:  24576, got: 524288)
[...]
Testing creation of a thread with stack size:  8372224
ThreadFunc:  ERROR, wrong stack size!  (Requested:  8372224, got: 524288)
Testing creation of a thread with stack size:  8380416
ThreadFunc:  ERROR, wrong stack size!  (Requested:  8380416, got: 524288)

... and here is the code:

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

static void * ThreadFunc(void * pDesiredStackSize)
{
   const size_t desiredStackSize = *((size_t *)pDesiredStackSize);

   pthread_attr_t tattr;
   if (pthread_attr_init(&tattr) == 0)
   {
      size_t actualStackSize;
      if (pthread_attr_getstacksize(&tattr, &actualStackSize) == 0)
      {
         if (actualStackSize == desiredStackSize)
         {
            printf("ThreadFunc:  Stack size is as expected:  %zu\n", actualStackSize);
         }
         else
         {
            printf("ThreadFunc:  ERROR, wrong stack size!  (Requested:  %zu, got: %zu)\n", desiredStackSize, actualStackSize);
         }
      }
      else perror("pthread_attr_getstacksize");
   }
   else perror("pthread_attr_init(2)");

   return NULL;
}

static void TestCustomStackSize(size_t desiredStackSizeBytes)
{
   printf("Testing creation of a thread with stack size:  %zu\n", desiredStackSizeBytes);

   pthread_attr_t attr;
   if (pthread_attr_init(&attr) != 0)
   {
      perror("pthread_attr_init");
      return;
   }

   int r = pthread_attr_setstacksize(&attr, desiredStackSizeBytes);
   if (r == 0)
   {
      pthread_t thread;
      if (pthread_create(&thread, &attr, ThreadFunc, &desiredStackSizeBytes) == 0)
      {
         if (pthread_join(thread, NULL) != 0) perror("pthread_join");
      }
      else perror("pthread_create");
   }
   else
   {
      perror("pthread_attr_setstacksize");
      printf("pthread_attr_setstacksize returned %i\n", r);
   }
}

int main(int argv, char ** argc)
{
   const int PAGE_SIZE=8*1024;
   for (size_t stackSizePages=1; stackSizePages<1024; stackSizePages++) TestCustomStackSize(stackSizePages*PAGE_SIZE);
   printf("Done!\n");
   return 0;
}
Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
  • After some further experimentation, it appears that pthread_attr_setstacksize() *is* working as expected, and that the discrepancy is caused by pthread_attr_getstacksize() not returning the stack size of the current thread, but rather the pthread library's default stack size. If so, then the question becomes, how does one actually query the current thread's stack size? – Jeremy Friesner Nov 25 '15 at 07:28
  • You may be after [pthread_attr_getstack()](http://linux.die.net/man/3/pthread_attr_getstack). Although probably not... – notmyfriend Nov 25 '15 at 08:24
  • This has been [asked before](http://stackoverflow.com/questions/53827/checking-available-stack-size-in-c), but none of the answers really feel very satisfactory. You'll probably have to find a platform-specific solution, if one exists. `getrlimit()` on Linux has an option to get the maximum stack size within a process, but apparently it's no longer used so might not be accurate these days. – notmyfriend Nov 25 '15 at 08:35

1 Answers1

3

The problem is that tattr doesn't refer to current thread's attribute. It's simply initialized as a brand new attribute, whereas pthread_attr_getstacksize() returns the given stack size set in the given attribute i.e. the attribute passed to it.

So, if you pass the correct attribute to pthread_attr_getstacksize(), it should work.

Call

  pthread_getattr_np(pthread_self(), &tattr);

before

  if (pthread_attr_getstacksize(&tattr, &actualStackSize) == 0)

instead of initializing the tattr.

Note pthread_getattr_np() is a non-standard function (not in POSIX).

P.P
  • 117,907
  • 20
  • 175
  • 238
  • 2
    Yes, this did the trick for Linux, thanks. Under MacOS/X, pthread_getattr_np() isn't available but `actualStackSize = pthread_get_stacksize_np(pthread_self());` does the same thing. – Jeremy Friesner Nov 25 '15 at 14:12
  • I don't think there's any POSIX function that can get the attribute. So if you really need a portable solution, then you may have to pass the attribute to the thread function. – P.P Nov 25 '15 at 15:31