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 ad68ca3..e4ebcc3 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 541610a..5041246 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 6a929a9..38a29e8 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; }