pthread_create()在291周期失败,EAGAIN

时间:2013-06-12 09:47:20

标签: c pthreads

我有这段代码:

int main(int argc, char** argv)
{
  pthread_t thread[thr_num];
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

  // just for debugging //
    struct rlimit rlim;
    getrlimit(RLIMIT_NPROC, &rlim);
    printf ("soft = %d \n", rlim.rlim_cur);
    printf ("hard = %d \n", rlim.rlim_max);
  ////

  for ( i = 1 ; i <= thr_num ; i++) {
    if(pthread_create( &thread[i], &attr, loggerThread, (void*)argv ) ) {
      printf("pthread_create failure, i = %d, errno = %d \n", i, errno);
      exit(1);
    }
  }

  pthread_attr_destroy(&attr);

  for ( i = 1 ; i <= thr_num ; i++) {
    if( pthread_join(thread[i], (void**)&status ) ) {
      exit(1);
    }
  }  

  return 0;
}

void* loggerThread(void* data) 
{
  char** sthg = ((char**)data);
  pthread_exit(NULL);
}

我不明白为什么当我用thr_num = 291运行这段代码时,我收到一个错误:     pthread_create失败,i = 291,errno = 11(EAGAIN)

与thr_num = 290工作正常。我在Linux 2.6.27.54-0.2-default(SLES 11)上运行此代码 rlim.rlim_cur的值也是6906 rlim.rlim_max。我用'ulimit -a'看到'最大用户进程'。 我还检查了/ proc / sys / kernel / threads-max(它是13813),由pthread_create手册页引导。 没有为'sysctl -a'输出找到任何值为290的参数。

偶尔我从这个链接中发现: pthread_create and EAGAIN :“即使调用pthread_exit或pthread_cancel,父进程仍然需要调用pthread_join来释放pthread ID,然后它将变为可循环使用”

所以我尝试将代码修改为:

for ( i = 1 ; i <= thr_num ; i++) {
  if(pthread_create( &thread[i], &attr, loggerThread, (void*)argv ) ) {
    printf("pthread_create failure, i = %d, errno = %d \n", i, errno);
    exit(1);
  }

  if( pthread_join(thread[i], (void**)&status ) ) {
    printf("pthread_join failure, i = %d, errno = %d \n", i, errno);
    exit(1);
  }     
}
pthread_attr_destroy(&attr);

然后一切正常:我没有在291周期得到错误。

我想了解为什么我的原始代码出现了错误: 1.因为线程编程错误 2.或者我达到了一些我无法识别的系统限制

还想知道我的纠正是否对这个问题有好处,或者我最终用这个解决方案引入了哪些隐藏的东西? 谢谢!

2 个答案:

答案 0 :(得分:6)

  

我想了解为什么我的原始代码出现了错误:1。因为错误   使用线程进行编程2.或者我达到了一些我无法识别的系统限制

您可能达到系统限制。可能你用完了地址空间。默认情况下,每个线程在linux上获得8-10Mb的堆栈空间。如果你创建了290个线程,那么它使用了接近3Gb的地址空间 - 这是32位进程的最大值。

在这种情况下你会得到EAGAIN,因为现在没有足够的资源来创建线程(因为当时没有足够的可用地址空间)。

当一个线程退出时,并不是所有线程资源都被释放(在linux上,整个线程堆栈都被保留了)。

  • 如果线程处于分离状态,例如你调用pthread_detach()或指定一个分离状态,当它被创建为pthread_create()的属性时,所有资源都在线程退出时释放 - 但你不能pthread_join()一个分离的线程。

    < / LI>
  • 如果线程未分离,则需要在其上调用pthread_join()以释放资源。

请注意,您在循环中调用pthread_join()的修改后的代码将:

  1. 产生一个线程
  2. 等待该线程完成
  3. 转到1
  4. 即。只有一个其他线程一次运行 - 这似乎有点无意义。

    你当然可以产生多个同时运行的线程 - 但这是一个限制。在您的机器上,您似乎发现限制在290左右。

答案 1 :(得分:2)

我最初把它写成评论,但以防万一......

您的代码:

  for ( i = 1 ; i <= thr_num ; i++) {
    if(pthread_create( &thread[i], &attr, loggerThread, (void*)argv ) ) {
      printf("pthread_create failure, i = %d, errno = %d \n", i, errno);
      exit(1);
    }
  }
...
  for ( i = 1 ; i <= thr_num ; i++) {
    if( pthread_join(thread[i], (void**)&status ) ) {
      exit(1);
    }
  }  

在两个for()循环中,你从1 - thr_num检查。这意味着你的数组线程[thr_num]超出范围,因为数组从索引0开始。因此,你应该从0迭代到比thr_num少一个:

for ( i = 0 ; i < thr_num ; i++)

我真的很惊讶你在将291作为thr_num之前没有得到分段错误。