title: PHP OOP Script using Multithreading, terminates unexpectedly
body: <p>Hi I'm having a problem trying to get threads to perform properly. The problem is that my php script will terminate unexpectedly at 1 of 2 specific points, during execution, and works the rest of the time.</p>
  
  <p><strong>I've created a test scenario that produces the same result:</strong></p>
  
  <p>This script creates 5 threads. Each thread adds up, each iteration, of a random number ranging from 10 to 20.</p>
  
  <p>Secondly, Summary_Thread checks to see when all threads are completed before printing the summary... and there in lies the issue.</p>
  
  <p>The script terminates during Summary_Thread::run and Stack_Item_Container_Stack::Compile_Summary, which is indirectly called at the end of Summary_Thread::run.</p>
  
  <pre><code>#!/usr/bin/php
  &lt;?php
  
  ini_set('max_execution_time', 0);
  ini_set('display_errors', 1);
  error_reporting(E_ALL ^ E_NOTICE);
  ignore_user_abort();
  
  class Summary_Thread_Container
  {
      public $stack_item_container_stack;
      private $summary_thread;
  
      function __construct($thread_count, Stack_Item_Container_Stack $stack_item_container_stack)
      {
          $this-&gt;stack_item_container_stack = $stack_item_container_stack;
  
          $this-&gt;summary_thread = new Summary_Thread($thread_count, $this);
          $this-&gt;summary_thread-&gt;start();
      }
  
      public function Compile_Summary(){ $this-&gt;stack_item_container_stack-&gt;Compile_Summary(); }
  }
  
  class Summary_Thread extends Worker
  {
      private $summary_thread_container;
      private $thread_count;
  
      function __construct($thread_count, Summary_Thread_Container $summary_thread_container)
      {
          $this-&gt;summary_thread_container = $summary_thread_container;
          $this-&gt;thread_count = $thread_count;
      }
  
      public function run()
      {
          $thread_count = 0;
  
          echo "\n**************************************  Stack Thread Count: {$this-&gt;thread_count} \n";
  
          echo "*** START.\n";
  
          if($this-&gt;thread_count == $thread_count)
              echo "*** THREAD COUNTS MATCH.\n";
          else
              echo "*** THREAD COUNTS DO NOT MATCH.\n";
  
          while($this-&gt;thread_count != $thread_count)
          {
              $temp_SIC = $this-&gt;summary_thread_container-&gt;stack_item_container_stack-&gt;first_stack_item_container;
              $thread_count = 0;
  
              while($temp_SIC)
              {
                  $thread_count++;
  
                  echo "**************************************  Thread Count: {$thread_count} \n";
  
                  $temp_SIC = $temp_SIC-&gt;Get_Next_Stack_Item_Container();
              }
  
              echo "*** END.\n";
  
              if($this-&gt;thread_count == $thread_count)
                  echo "*** THREAD COUNTS MATCH.\n";
              else
                  echo "*** THREAD COUNTS DO NOT MATCH.\n";
          }
  
          $this-&gt;Compile_Summary();
      }
  
      public function Compile_Summary(){ $this-&gt;summary_thread_container-&gt;Compile_Summary(); }
  }
  
  class Stack_Item_Container_Stack
  {
      public $first_stack_item_container;
      private $thread_count;
      private $summary_thread_container;
  
      function __construct()
      {
          $this-&gt;first_stack_item_container = null;
          $this-&gt;thread_count = 0;
  
          for($i = 0; $i &lt; 5; $i++)
          {
              echo "       * Creating Stack Item Container: {$i}\n";
  
              $this-&gt;thread_count++;
              $this-&gt;Add_Stack_Item_Container(new Stack_Item_Container(rand(10, 20), $i, $this));
          }
  
          $this-&gt;summary_thread_container = new Summary_Thread_Container($this-&gt;thread_count, $this);
      }
  
      public function Add_Stack_Item_Container(Stack_Item_Container $stack_item_container)
      {
          echo "       * Adding Stack Item Container *\n";
  
          if($this-&gt;first_stack_item_container)
          {
              $temp_stack_item_container = $this-&gt;first_stack_item_container;
  
              while($temp_stack_item_container-&gt;Get_Next_Stack_Item_Container())
                  $temp_stack_item_container = $temp_stack_item_container-&gt;Get_Next_Stack_Item_Container();
  
              $temp_stack_item_container-&gt;Set_Next_Stack_Item_Container($stack_item_container);
          }
          else $this-&gt;first_stack_item_container = $stack_item_container;
      }
  
      public function Compile_Summary()
      {
          echo "\n";
          echo "===============\n";
          echo "=== Summary ===\n";
          echo "===============\n";
          echo "\n";
  
          $temp_SIC = $this-&gt;first_stack_item_container;
  
          while($temp_SIC)
          {
              echo "    Thread ID {$temp_SIC-&gt;member_variables[0]} ({$temp_SIC-&gt;member_variables[4]}) has a Total of {$temp_SIC-&gt;member_variables[2]}";
              echo "\n";
  
              $temp_SIC = $temp_SIC-&gt;Get_Next_Stack_Item_Container();
          }
  
          echo "\n";
  
          $this-&gt;Kill();
      }
  
      private function Kill()
      {
          while($this-&gt;first_stack_item_container)
          {
              $temp_SIC = $this-&gt;first_stack_item_container;
  
              $this-&gt;first_stack_item_container = $this-&gt;first_stack_item_container-&gt;Get_Next_Stack_Item_Container();
  
              $temp_SIC-&gt;Kill();
          }
  
          unset($this-&gt;summary_thread_container);
          unset($this);
      }
  }
  
  class Stack_Item_Container
  {
      private $stack_item_container_stack;
      private $next_stack_item_container;
  
      public $member_variables;
  
      public $stack_item_thread;
  
      function __construct($time, $index, Stack_Item_Container_Stack $stack_item_container_stack)
      {
          $this-&gt;stack_item_container_stack = $stack_item_container_stack;
          $this-&gt;next_stack_item_container = null;
  
          $this-&gt;member_variables = new Stackable();
          $this-&gt;member_variables[] = -1;
          $this-&gt;member_variables[] = $time;
          $this-&gt;member_variables[] = 0;
          $this-&gt;member_variables[] = false;
          $this-&gt;member_variables[] = $index;
  
          $this-&gt;stack_item_thread = new Stack_Item_Thread($this-&gt;member_variables, $this);
          $this-&gt;stack_item_thread-&gt;start();
      }
  
      public function Get_Stack_Item_Container_Stack(){ return $this-&gt;stack_item_container_stack; }
  
      public function Get_Next_Stack_Item_Container(){ return $this-&gt;next_stack_item_container; }
      public function Set_Next_Stack_Item_Container(Stack_Item_Container $next_SIC){ $this-&gt;next_stack_item_container = $next_SIC; }
  
      public function Kill()
      {
          $this-&gt;stack_item_thread-&gt;kill();
          unset($this-&gt;member_variables);
          unset($this);
      }
  }
  
  class Stack_Item_Thread extends Worker
  {
      private $stack_item_container;
      private $member_variables;
  
      function __construct($member_variables, Stack_Item_Container $stack_item_container)
      {
          $this-&gt;member_variables = $member_variables;
          $this-&gt;stack_item_container = $stack_item_container;
      }
  
      public function run()
      {
          $this-&gt;member_variables[0] = $this-&gt;getThreadId();
          $total = 0;
  
          echo "\n";
  
          for($i = 0; $i &lt; $this-&gt;member_variables[1]; $i++)
          {
              $total += $i;
              $val = $i + 1;
  
              echo "Thread ID ({$this-&gt;member_variables[4]}): {$this-&gt;member_variables[0]}:";
              echo " Count: {$val} of {$this-&gt;member_variables[1]}";
              echo "\n";
          }
  
          echo "\n";
  
          $this-&gt;member_variables[2] = $total;
          $this-&gt;member_variables[3] = true;
      }
  }
  
  $stack_item_container_stack = new Stack_Item_Container_Stack();
  </code></pre>
  
  <p>OUTPUT 1 (When it does work):</p>
  
  <pre><code>**************************************  Stack Thread Count: 5
  *** START.
  *** THREAD COUNTS DO NOT MATCH.
  **************************************  Thread Count: 1
  **************************************  Thread Count: 2
  **************************************  Thread Count: 3
  **************************************  Thread Count: 4
  **************************************  Thread Count: 5
  *** END.
  *** THREAD COUNTS MATCH.
  
  ===============
  === Summary ===
  ===============
  
      Thread ID 139975400195840 (0) has a Total of 105
      Thread ID 139975389705984 (1) has a Total of 153
      Thread ID 139975378360064 (2) has a Total of 153
      Thread ID 139975367014144 (3) has a Total of 55
      Thread ID 139975130801920 (4) has a Total of 153
  </code></pre>
  
  <p>OUTPUT 2: (the first point that it will terminate):</p>
  
  <pre><code>**************************************  Stack Thread Count: 5
  *** START.
  *** THREAD COUNTS DO NOT MATCH.
  </code></pre>
  
  <p>OUTPUT 3: (the second point that it will terminate)</p>
  
  <pre><code>**************************************  Stack Thread Count: 5
  *** START.
  *** THREAD COUNTS DO NOT MATCH.
  **************************************  Thread Count: 1
  **************************************  Thread Count: 2
  **************************************  Thread Count: 3
  **************************************  Thread Count: 4
  **************************************  Thread Count: 5
  *** END.
  *** THREAD COUNTS MATCH.
  </code></pre>
  
  <p>Just to give you as much information as i can:
  (might not be relevant but just in case)</p>
  
  <h2>Changes made to config:</h2>
  
  <p>File: /etc/sysctl.conf, Changes Made: net.ipv4.tcp_fin_timeout=10</p>
  
  <p>File: php.ini, Changes Made: extension=php_pthreads.dll</p>
  
  <h2>Server:</h2>
  
  <p>Linux 2.6.32-504.8.1.el6.x86_64</p>
  
  <p>PHP 5.5.13</p>
  
  <p>Apache/2.2.15 (CentOS)</p>
  
  <p>Max Requests    Per Child: 4000 - Keep Alive: off - Max Per Connection: 100</p>
  
  <p>Timeouts        Connection: 60 - Keep-Alive: 15</p>
  
  <p>Virtual Server  No</p>
  
  <hr>
  
  <p>Please help :) and questions would help ... anything i'm not seeing?</p>
  
  <p>Thanks in advance</p>