3

I am using tornado. I hope the following is easy to understand, It's spawning a tcproute process and sending the output to the websocket's other end.

class TracerouteHandler(tornado.websocket.WebSocketHandler):
  def open(self,ip):
    p = subprocess.Popen(['traceroute',ip],stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    while p.poll() is None: #running
      line=p.stdout.readline()
      if line!=None and len(line)>0:
        self.write_message(json.dumps({'stdout':line})) 
    self.write_message(json.dumps({'stdout':'Done! For red marked ip addresses, the location couldn\'t be determined with <a href="http://hostip.info">hostip.info</a>. If you know the correct location, please update it there.'}))

The problem is that due to the while p.poll() is None loop, tornado blocks. Also, if there's nothing in p.stdout to read, the p.stdout.readline blocks. So I'd like to have some sort of callback mechanism that gets fired when I have something new in p.stdout. How do I do that?

prongs
  • 9,422
  • 21
  • 67
  • 105

1 Answers1

1

Use Queue, a non-blocking messaging mechanism which comes with Python.

There is a really nice implementation in this answer, where a separate Thread reads output line from the process, and writes them to the Queue. The main thread can read from the queue in a non-blocking fashion.

Thanks to Andrew for the link in the comment.

Community
  • 1
  • 1
Adam Matan
  • 128,757
  • 147
  • 397
  • 562