pretty

Wednesday 17 June 2015

C++ 11 when do detached threads termiante?


What is the fate of the thread that is detached via std::thread::detach()? In the common situation the detached thread would be abandoned when the std::exit() would be called, and std::exit() is called on return from main() whether there are additional threads in the process or not.
#include "stdlib.h"
#include "stdio.h"
#include "unistd.h"
#include "string"
#include "pthread.h"

class Global {
public:
    ~Global()
    {
        std::cout << "Global object dtor\n";
    }
};

class A {
  public:
  ~A()
  {
     std::cout << "A dtor\n";
  }
};

void thread_main()
{
  int i = 0;
  A a;
  while (true) {
   std::cout << "thread_main" << i++ << std::endl;
   sleep(1);

   if (i == 5) break;
  }
}

void atexit_handler()
{
    std::cout << "atexit handler\n";
}

Global global_variable; 

int main(int argc, char **argv)
{
  const int result = std::atexit(atexit_handler);
  std::thread t(thread_main);
  t.detach();
  return 0;
}
This snippet would produce the following output, note that the destructor for the object allocated on detached thread is not getting called.
atexit handler
thread_main0
Global object dtor
*** Exited normally ***
So the thread is abandoned non-gracefully, in a manner that reminds of the daemon thread in Java. Really, while JVM would not finish application if there is at least one active non-daemon thread, but if the thread is daemon thread it's existence wouldn't prevent app from exiting, and such thread would be abandoned - no stack unwinding, no finally blocks getting called for it. Such threads are used for tasks like garbage collection.

What if std::exit() would not be called from main()? In the following snippet I'm finishing the main thread without calling return and hence exit() is not getting called, because there's still a running thread around.
int main(int argc, char **argv)
{
  const int result = std::atexit(atexit_handler);
  std::thread t(thread_main);
  t.detach();
  pthread_exit(NULL);
  //return 0;
}
This will let the detached thread complete and then the process exits releasing all the resources.
thread_main0
thread_main1
thread_main2
thread_main3
thread_main4
A dtor
atexit handler
Global object dtor
*** Exited normally ***

No comments :

Post a Comment