title: What could make a connection.send() block ? (from conn1, conn2 = multiprocessing.Pipe() )
body: <p>I am debugging application that gather information from 2 sensors : a webcam and a microphone. </p>
  
  <p>The general architecture is quite simple : </p>
  
  <ul>
  <li>the main process sends messages (start, stop, get_data) via pipes to the child processes (one for each).</li>
  <li>child processes gather the data and send it to the main process</li>
  </ul>
  
  <p>Child &amp; main processes are in infinite loops to process commands (the main process from the user, the child process from the main process).</p>
  
  <p>It globally works but I have trouble stopping the child processes. </p>
  
  <p>I have logged the code and it seems to happen 2 things :</p>
  
  <ol>
  <li>The 'stop' message is sent but doesn't get through the pipe.</li>
  <li>The child process continue to send data and the conn.send(data) blocks.</li>
  </ol>
  
  <p>The behavior is clearly linked to the state of the connection, as child processes that send nothing back don't have this behavior. Still, I don't see how to debug/modify the current architecture which seems reasonnable.</p>
  
  <p>So, what cause this blocking behavior and how to avoid it ?</p>
  
  <p>This is the code which is executed for each iteration of the infinite loop in the child process : </p>
  
  <pre><code>    def do(self):
          while self.cnx.poll():
              msg = self.cnx.recv()
              self.queue.append(msg)
          #==
          if not self.queue:
              func_name = 'default_action'
              self.queue.append([func_name, ])
          #==
          msg             = self.queue.pop()
          func_name, args = msg[0], msg[1:]
          #==
          res = self.target.__getattribute__(func_name)(*args)
          #==
          running = func_name != 'stop'
          #==
          if res and self.send:
              assert running
              self.output_queue.append(res[0])
          if self.output_queue and running:
              self.cnx.send(self.output_queue.popleft())
          #==
          return running
  </code></pre>
  
  <p><strong>update</strong> : it seems that the Pipe cannot be written simultaneously on both end. It works if change the last few lines of the above code to :</p>
  
  <pre><code>        if self.output_queue and running:
              if not self.cnx.poll(): 
                  self.cnx.send(self.output_queue.popleft())
  </code></pre>
  
  <p>The question stays open though as Pipe are documented as full duplex by default and this behavior is not documented at all. I must have misunderstood something. Please, enlight me! </p>
  
  <p><strong>update 2</strong> : just to be clear, no connection is closed during in this situation. To describe the sequence of events :</p>
  
  <ul>
  <li>the main process sends a messsage ("stop") (it empties the connection before sending the message)</li>
  <li>the main process enter an (infinite) loop that stops when the child process is terminated.</li>
  <li>meanwhile, the child process is blocked in the send and never gets the message.</li>
  </ul>