Reason for ENOMEM failure to create threads?

核能气质少年 提交于 2020-01-04 06:08:07

问题


I have an application that is using pthread_create() and pthread_detach() in the main thread and later pthread_exit() in the child thread.

After around 54 pthread_create() calls that have each been paired with a subsequent pthread_detach() and then pthread_exit() the pthread_create() fails. It is ENOMEM failure "Out of memory".

What might cause pthread_exit() to not be freeing up the memory of the old threads and causing my application to leak memory and eventually run out?

This is running on Linux Centos 5 64 bit but a 32 bit built application.

Here is the code to create the thread which calls both pthread_create() and pthread_detach().

int
_createThread()
{
  pthread_attr_t attr;
  int return_val;

  return_val = setupMutex(_Mtx());

  if (return_val != 0) {
    return return_val;
  }

  return_val = setupCond(_StartCond());

  if (return_val != 0) {
    return return_val;
  }

  return_val = setupCond(_EndCond());

  if (return_val != 0) {
    return return_val;
  }

  return_val = pthread_attr_init(&attr);

  if (return_val != 0) {
    return -1;
  }

  size_t stackSize = 1024 * 1024 * 64; // Our default stack size 64MB.

  return_val = pthread_attr_setstacksize(&attr, stackSize);

  if (return_val != 0) {
    return -1;
  }

  int tries = 0;

 retry:
  // _initialize() gets called by the thread once it is created.
  return_val = pthread_create(&_threadId, &attr,
                              (void *(*)(void *))_initialize,
                              (void *)this);

  if (return_val != 0) {
    if (return_val == EAGAIN) {
      if (++tries < 10) {
        Exit::deferredWarning(Exit::eagainThread);
        goto retry;
      }
    }
    return -1;
  }

  return_val = pthread_attr_destroy(&attr);

  if (return_val != 0) {
    return -1;
  }

  return_val = pthread_detach(_threadId);

  if (return_val != 0) {
    return -1;
  }

  // Wait for the new thread to finish starting up.
  return_val = waitOnCond(_Mtx(), _EndCond(), &_endCount, 10 /* timeout */, 0,
                          "_createThread-end");

  if (return_val != 0) {
    return -1;
  }

  return 0;
}

void
_exitThread()
{
  (void) releaseCond(_Mtx(), _EndCond(), &_endCount, "_exitThread-end");
  pthread_exit(NULL);
}

回答1:


Call pthread_join before pthread_exit so the thread can cleanup before exiting.




回答2:


The explanation is in the man page of pthread_create :

When a detached thread terminates, its resources are automatically released back to the system without the need for another thread to join with the terminated thread

So if you neither detach it nore join it you loose some resources which finally raises the ENOMEM.

You should either detach the thread or join it from its parent thread.




回答3:


Will, I've deleted my old answer because it seems that I was mistaken. Along this line, I have a question: How did you get ENOMEM? Did you check "errno" as I had indicated in my answer? Because pthread_create is an exception to the rule, and does not set errno; instead, the error is returned as a result.

Correct way of getting failure reason:

int err = pthread_create(...);
if(err)
{
    perror( "Error creating thread" );
    printf( "Error: %s\n", strerror( err ) );
    return false;
}

The reason I ask is because pthread_create will never fail with ENOMEM! In case of no memory, pthread_create will return EAGAIN. Refer to http://sourceware.org/ml/glibc-bugs/2007-11/msg00007.html for info on EAGAIN vs ENOMEM

EDIT

Obvious question: the system does have enough free memory left, right?




回答4:


call pthread_join() or alternatively pthread_detatch() if joining doesn't work for your use case.

this error occurs because the library is storing the exit codes of all terminated threads, waiting to pass them back to you via pthread_join(). alternatively, if you do not care about the thread's exit code, call pthread_detatch() after creating it. this tells the API that you do not care about its return code, so it doesn't need to store it.



来源:https://stackoverflow.com/questions/4530787/reason-for-enomem-failure-to-create-threads

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!