title: Handling kill events for python multiprocessing processes
body: <p>For a program that should run both on Linux and Windows (python 2.7), I'm trying to update values of a given object using <code>multiprocessing.Process</code>  (while the main program is running, I'm calling the update class by a separate process).</p>
  
  <p>Sometimes it takes too long before my object is updated, so I want to be able to kill my update process, and to continue with the main program. "Too long" is not strictly defined here, but rather a subjective perception of the user.
  For a single queue (as in the MyFancyClass example in <a href="http://pymotw.com/2/multiprocessing/communication.html" rel="nofollow">http://pymotw.com/2/multiprocessing/communication.html</a>) I can kill the update process and the main program continues as I want.
  However, when I make a second queue to retrieve the updated object, ending the update process does not allow me to continue in the main program.</p>
  
  <p>What I have so far is:</p>
  
  <pre><code>import multiprocessing
  import time, os
  
  class NewParallelProcess(multiprocessing.Process):
  
      def __init__(self, taskQueue, resultQueue, processName):
          multiprocessing.Process.__init__(self)
          self.taskQueue      = taskQueue
          self.resultQueue    = resultQueue
          self.processName    = processName
  
  
      def run(self):
          print "pid %s of process that could be killed" % os.getpid()
          while True:
              next_task = self.taskQueue.get()
              if next_task is None:
                  # poison pill for terminate
                  print "%s: exiting" % self.processName
                  self.taskQueue.task_done()
                  break
              print "%s: %s" % (self.processName, next_task)
              answer = next_task()
              self.taskQueue.task_done()
              self.resultQueue.put(answer)
  
          return
  
  
  
  class OldObject(object):
      def __init__(self):
          self.accurate       = "OldValue"
          self.otherValue     = "SomeOtherValue"
  
  
  
  class UpdateObject(dict):
      def __init__(self, objectToUpdate):
          self.objectToUpdate = objectToUpdate
  
      def __call__(self):
          returnDict = {}
          returnDict["update"]    = self.updateValue("NewValue")
          return returnDict
  
      def __str__(self):
          return "update starting"
  
      def updateValue(self, updatedValue):
          for i in range(5):
              time.sleep(1) # updating my object - time consuming with possible pid kill
              print "working... (pid=%s)" % os.getpid()
  
          self.objectToUpdate.accurate = updatedValue
          return self.objectToUpdate
  
  
  
  
  if __name__ == '__main__':
      taskQueue   = multiprocessing.JoinableQueue()
      resultQueue     = multiprocessing.Queue()
      newProcess  = NewParallelProcess(taskQueue, resultQueue, processName="updateMyObject")
      newProcess.start()
  
      myObject = OldObject()  
      taskQueue.put(UpdateObject(myObject))
  
      # poison pill for NewParallelProcess loop and wait to finish
      taskQueue.put(None)
      taskQueue.join()
  
      # get back results
      results = resultQueue.get()
      print "Values have been updated"
      print "---&gt; %s became %s" % (myObject.accurate, results["update"].accurate)
  </code></pre>
  
  <p>Any suggestions on how to kill the newProcess and to continue in the main program? </p>
  
  <p>Well, made some modifications, and this does what I want. Not sure whether it is the most efficient, so any improvements are always welcome :)</p>
  
  <pre><code>import multiprocessing
  import time, os
  
  class NewParallelProcess(multiprocessing.Process):
  
      def __init__(self, taskQueue, resultQueue, processName):
          multiprocessing.Process.__init__(self)
          self.taskQueue      = taskQueue
          self.resultQueue    = resultQueue
          self.name       = processName
  
  
      def run(self):
          print "Process %s (pid = %s) added to the list of running processes" % (self.name, self.pid)
          next_task = self.taskQueue.get()
  
          self.taskQueue.task_done()
          self.resultQueue.put(next_task())
  
          return
  
  
  
  class OldObject(object):
      def __init__(self):
          self.accurate       = "OldValue"
          self.otherValue     = "SomeOtherValue"
  
  
  
  class UpdateObject(dict):
      def __init__(self, objectToUpdate, valueToUpdate):
          self.objectToUpdate = objectToUpdate
          self.valueToUpdate = valueToUpdate
  
  
      def __call__(self):
          returnDict = {}
          returnDict["update"]    = self.updateValue(self.valueToUpdate)
          return returnDict
  
  
      def updateValue(self, updatedValue):
          for i in range(5):
              time.sleep(1) # updating my object - time consuming with possible pid kill
              print "working... (pid=%s)" % os.getpid()
  
          self.objectToUpdate.accurate = updatedValue
          return self.objectToUpdate
  
  
  
  
  if __name__ == '__main__':
      # queue for single process
      taskQueue   = multiprocessing.JoinableQueue()
      resultQueue     = multiprocessing.Queue()
      newProcess  = NewParallelProcess(taskQueue, resultQueue, processName="updateMyObject")
      newProcess.start()
  
      myObject = OldObject()  
      taskQueue.put(UpdateObject(myObject, "NewValue"))
  
  
      while True:
          # check if newProcess is still alive
          time.sleep(5)
          if newProcess.is_alive() is False:
              print "Process %s (pid = %s) is not running any more (exit code = %s)" % (newProcess.name, newProcess.pid, newProcess.exitcode)
              break
  
  
      if newProcess.exitcode == 0:
          print "ALL OK"
          taskQueue.join()
  
          # get back results
          print "NOT KILLED"
  
          results = resultQueue.get()
          print "Values have been updated"
          print "---&gt; %s became %s" % (myObject.accurate, results["update"].accurate)
  
  
      elif newProcess.exitcode == 1:
          print "ended with error in function"
          print "KILLED"
          for i in range(5):
              time.sleep(1)
              print "i continue"
  
  
      elif newProcess.exitcode == -15 or newProcess.exitcode == -9:
          print "ended with kill signal %s" % newProcess.exitcode
          print "KILLED"
          for i in range(5):
              time.sleep(1)
              print "i continue"
  
  
      else:
          print "no idea what happened"
          print "KILLED"
          for i in range(5):
              time.sleep(1)
              print "i continue"
  </code></pre>