]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Fix a possible crash in thread_is_available()
[stockfish] / src / search.cpp
index f259c8fb5938822d9fe1093de1842a7cb7274e16..7c341f878f7200d321343567c249ec8fcd8964f0 100644 (file)
@@ -1643,7 +1643,7 @@ namespace {
     StateInfo st;
     Move ttMove, move;
     Value staticValue, bestValue, value, futilityBase, futilityValue;
-    bool isCheck, enoughMaterial, moveIsCheck;
+    bool isCheck, enoughMaterial, moveIsCheck, evasionPrunable;
     const TTEntry* tte = NULL;
     int moveCount = 0;
     bool pvNode = (beta - alpha != 1);
@@ -1744,8 +1744,15 @@ namespace {
           }
       }
 
-      // Don't search captures and checks with negative SEE values
-      if (   !isCheck
+      // Detect blocking evasions that are candidate to be pruned
+      evasionPrunable =   isCheck
+                       && bestValue != -VALUE_INFINITE
+                       && !pos.move_is_capture(move)
+                       && pos.type_of_piece_on(move_from(move)) != KING
+                       && !pos.can_castle(pos.side_to_move());
+
+      // Don't search moves with negative SEE values
+      if (   (!isCheck || evasionPrunable)
           &&  move != ttMove
           && !move_is_promotion(move)
           &&  pos.see_sign(move) < 0)
@@ -2891,7 +2898,10 @@ namespace {
     if (!Threads[slave].idle || slave == master)
         return false;
 
-    if (Threads[slave].activeSplitPoints == 0)
+    // Make a local copy to be sure doesn't change under our feet
+    int localActiveSplitPoints = Threads[slave].activeSplitPoints;
+
+    if (localActiveSplitPoints == 0)
         // No active split points means that the thread is available as
         // a slave for any other thread.
         return true;
@@ -2899,8 +2909,10 @@ namespace {
     if (ActiveThreads == 2)
         return true;
 
-    // Apply the "helpful master" concept if possible
-    if (SplitPointStack[slave][Threads[slave].activeSplitPoints - 1].slaves[master])
+    // Apply the "helpful master" concept if possible. Use localActiveSplitPoints
+    // that is known to be > 0, instead of Threads[slave].activeSplitPoints that
+    // could have been set to 0 by another thread leading to an out of bound access.
+    if (SplitPointStack[slave][localActiveSplitPoints - 1].slaves[master])
         return true;
 
     return false;
@@ -2986,6 +2998,7 @@ namespace {
         splitPoint->slaves[i] = 0;
 
     Threads[master].idle = false;
+    Threads[master].stop = false;
     Threads[master].splitPoint = splitPoint;
 
     // Allocate available threads setting idle flag to false
@@ -2993,6 +3006,7 @@ namespace {
         if (thread_is_available(i, master))
         {
             Threads[i].idle = false;
+            Threads[i].stop = false;
             Threads[i].splitPoint = splitPoint;
             splitPoint->slaves[i] = 1;
             splitPoint->cpus++;
@@ -3003,21 +3017,14 @@ namespace {
     // We can release the lock because master and slave threads are already booked
     lock_release(&MPLock);
 
-    // Copy the tail of current search stack to the master thread
-    memcpy(splitPoint->sstack[master] + ply - 1, sstck + ply - 1, 3 * sizeof(SearchStack));
-
     // Tell the threads that they have work to do. This will make them leave
-    // their idle loop. Also copy search stack tail for each slave thread.
+    // their idle loop. But before copy search stack tail for each thread.
     for (int i = 0; i < ActiveThreads; i++)
-    {
         if (i == master || splitPoint->slaves[i])
         {
-            Threads[i].workIsWaiting = true;
-            Threads[i].stop = false;
-        }
-        if (splitPoint->slaves[i])
             memcpy(splitPoint->sstack[i] + ply - 1, sstck + ply - 1, 3 * sizeof(SearchStack));
-    }
+            Threads[i].workIsWaiting = true; // This makes the slave to exit from idle_loop()
+        }
 
     // Everything is set up. The master thread enters the idle loop, from
     // which it will instantly launch a search, because its workIsWaiting