1
0
Fork 0

Terminate threads before to exit main()

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>
sf_2.3.1_base
Marco Costalba 2012-08-29 16:43:01 +02:00
parent 0a003d3ba1
commit 8dcb4bc3cc
3 changed files with 7 additions and 5 deletions

View 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();
}

View 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];

View 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; }