Terminate threads before to exit main()
authorMarco Costalba <mcostalba@gmail.com>
Wed, 29 Aug 2012 14:43:01 +0000 (16:43 +0200)
committerMarco Costalba <mcostalba@gmail.com>
Wed, 29 Aug 2012 17:11:44 +0000 (19:11 +0200)
It is very difficult and risky to assure
that a running thread doesn't access a global
variable. This is currently true, but could
change in the future and we don't want to rely
on code that works 'by accident'. The threads
are still running when ThreadPool destructor is
called (after main() returns) and this could
lead to crashes if a thread accesses a global
that has been already freed. The solution is to
use an exit() function and call it while we are
still in main(), ensuring global variables are
still alive at threads termination time.

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/main.cpp
src/thread.cpp
src/thread.h

index ad68ca35fe47113ba8d6ad31937a4bc7dc1ce0ef..e4ebcc30140d5550c9b216d15da2a1833ecdb661 100644 (file)
@@ -37,8 +37,8 @@ int main(int argc, char* argv[]) {
   Zobrist::init();
   Bitbases::init_kpk();
   Search::init();
-  Threads.init();
   Eval::init();
+  Threads.init();
   TT.set_size(Options["Hash"]);
 
   std::string args;
@@ -47,4 +47,6 @@ int main(int argc, char* argv[]) {
       args += std::string(argv[i]) + " ";
 
   UCI::loop(args);
+
+  Threads.exit();
 }
index 541610a1ca4b2bd5a63d16323c4d2aed991aae21..50412468ebb83222caf15a8b4b9835f018b7aa63 100644 (file)
@@ -196,9 +196,9 @@ void ThreadPool::init() {
 }
 
 
-// d'tor cleanly terminates the threads when the program exits.
+// exit() cleanly terminates the threads before the program exits.
 
-ThreadPool::~ThreadPool() {
+void ThreadPool::exit() {
 
   for (size_t i = 0; i < threads.size(); i++)
       delete threads[i];
index 6a929a98af1cdc44bbd9d703f5dfb597f71cfb23..38a29e8dc00d6c07bd88f097830ff8ce3d378a4c 100644 (file)
@@ -130,8 +130,8 @@ public:
 class ThreadPool {
 
 public:
-  void init(); // No c'tor, Threads object is global and engine shall be fully initialized
- ~ThreadPool();
+  void init(); // No c'tor and d'tor, threads rely on globals that should
+  void exit(); // be initialized and valid during the whole thread lifetime.
 
   Thread& operator[](size_t id) { return *threads[id]; }
   bool use_sleeping_threads() const { return useSleepingThreads; }