【问题标题】:Why is pthread_attr_setstacksize() not working for me?为什么 pthread_attr_setstacksize() 对我不起作用?
【发布时间】:2016-02-27 18:53:57
【问题描述】:

我刚才注意到,当我使用 pthread_create() 生成线程时,我为线程设置自定义堆栈大小的请求似乎被忽略了。特别是,如果我从派生线程中调用 pthread_attr_getstacksize(),它总是报告默认堆栈大小,无论我要求什么。

在 Linux 和 MacOS/X 下都可以看到这种行为,所以我怀疑我做错了什么,但我不知道它是什么。

要重现该问题,请编译并运行以下代码(通过“g++ stack_test.cpp -lpthread ; ./a.out”)。它尝试了一堆不同的堆栈大小,如果它的请求没有得到满足,它就会抱怨。有问题的输出如下所示:

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)

...这里是代码:

#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;
}

【问题讨论】:

  • 经过进一步的实验,看来 pthread_attr_setstacksize() 正在按预期工作,并且差异是由于 pthread_attr_getstacksize() 未返回当前线程的堆栈大小造成的,而是 pthread 库的默认堆栈大小。如果是这样,那么问题就变成了,如何真正查询当前线程的堆栈大小?
  • 你可能在pthread_attr_getstack()之后。虽然可能不是……
  • 这一直是asked before,但没有一个答案真的让人觉得很满意。如果存在,您可能必须找到特定于平台的解决方案。 Linux 上的getrlimit() 可以选择在进程中获取最大堆栈大小,但显然它已不再使用,因此这些天可能不准确。

标签: c++ multithreading stack pthreads


【解决方案1】:

问题是tattr 没有引用当前线程的属性。它只是简单地初始化为一个全新的属性,而pthread_attr_getstacksize() 返回给定属性中设置的给定堆栈大小,即传递给它的属性。

因此,如果您将正确的属性传递给pthread_attr_getstacksize(),它应该可以工作。

打电话

  pthread_getattr_np(pthread_self(), &tattr);

之前

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

而不是初始化tattr

注意pthread_getattr_np() 是一个非标准函数(不在 POSIX 中)。

【讨论】:

  • 是的,这对 Linux 有帮助,谢谢。在 MacOS/X 下,pthread_getattr_np() 不可用,但actualStackSize = pthread_get_stacksize_np(pthread_self()); 做同样的事情。
  • 我认为没有任何 POSIX 函数可以获取该属性。所以如果你真的需要一个可移植的解决方案,那么你可能必须将属性传递给线程函数。
猜你喜欢
  • 2010-10-08
  • 2019-01-13
  • 2015-09-07
  • 1970-01-01
  • 2023-04-03
  • 2011-09-04
  • 2011-10-15
  • 1970-01-01
  • 2019-07-11
相关资源
最近更新 更多