title: multiprocessing spawning processes without pooling
body: <p>I am trying to use the multiprocessing library to spawn new processes without using a Pool and without creating zombies.</p>
  <blockquote>
  <p>On Unix when a process finishes but has not been joined it becomes a
  zombie. There should never be very many because each time a new
  process starts (or <code>active_children()</code> is called) all completed
  processes which have not yet been joined will be joined. Also calling
  a finished process’s <code>Process.is_alive</code> will join the process. Even so
  it is probably good practice to explicitly join all the processes that
  you start.</p>
  </blockquote>
  <p>This implementation is a short version of a bigger script that creates zombies after some hours :</p>
  <pre><code>from multiprocessing import Process
  import time
  
  def target(task):
      print(f&quot;Working for {task*2} seconds ...&quot;)
      time.sleep(task*2)
  
  if __name__ == '__main__':
      processes = 4
      list_process = [None] * processes
      targets = [[2] for i in range(10)]
  
      list_process = [None] * processes
      while targets:
          for i in range(processes):
              p = list_process[i]
              if not (p and p.is_alive()):
                  list_process[i] = Process(target=target, args=(targets.pop(0)))
                  list_process[i].start()
                  if p:
                      p.join()
  
      for process in list_process:
          if process:
              process.join()
  </code></pre>
  <p>On the bigger version, <code>list_process</code> has only zombies and no more task can be processed.</p>
  <p><strong>Update 1</strong></p>
  <p>Thanks to <a href="https://stackoverflow.com/users/2823719/booboo">Booboo</a>, I was able to get better sight of what is happening :</p>
  <pre><code>from multiprocessing import Process
  import time
  
  def target(task):
      print(f&quot;Working for {task*2} seconds ...&quot;)
      time.sleep(task*2)
  
  if __name__ == '__main__':
      started_count = 0
      joined_count = 0
      joined_list = []
      processes = 4
      list_process = [None] * processes
      targets = [[2] for i in range(10)]
  
      list_process = [None] * processes
      while targets:
          for i in range(processes):
              p = list_process[i]
              if not (p and p.is_alive()):
                  list_process[i] = Process(target=target, args=(targets.pop(0)))
                  list_process[i].start()
                  print(list_process[i].pid)
                  started_count += 1
                  if p:
                      assert(not p.is_alive())
                      p.join()
                      joined_list.append(list_process[i].pid)
                      joined_count += 1
  
      for process in list_process:
          if process:
              process.join()
              joined_list.append(list_process[i].pid)
              joined_count += 1
  
      print(f'Final started count: {started_count}, final joined count: {joined_count}')
      print(joined_list)
  </code></pre>
  <p>Output :</p>
  <pre><code>20604
  24108
  1272
  23616
  Working for 4 seconds ...
  Working for 4 seconds ...
  Working for 4 seconds ...
  Working for 4 seconds ...
  18492
  17348
  19992
  6216
  Working for 4 seconds ...
  Working for 4 seconds ...
  Working for 4 seconds ...
  Working for 4 seconds ...
  18744
  26240
  Working for 4 seconds ...
  Working for 4 seconds ...
  Final started count: 10, final joined count: 10
  [18492, 17348, 19992, 6216, 18744, 26240, 6216, 6216, 6216, 6216]
  </code></pre>
  <p>I have 10 processes that are joined but some are not the good ones (the pid <em>6216</em> has not been invoked for a task, and the first ones are not joined), leading to not joined processes, why ?</p>