title: How do I stop Tornado web server?
body: <p>I've been playing around a bit with the <a href="http://www.tornadoweb.org/">Tornado web server</a> and have come to a point where I want to stop the web server (for example during unit testing). The following simple example <a href="http://www.tornadoweb.org/documentation#overview">exists on the Tornado web page</a>:</p>
  
  <pre><code>import tornado.ioloop
  import tornado.web
  
  class MainHandler(tornado.web.RequestHandler):
      def get(self):
          self.write("Hello, world")
  
  application = tornado.web.Application([
      (r"/", MainHandler),
  ])
  
  if __name__ == "__main__":
      application.listen(8888)
      tornado.ioloop.IOLoop.instance().start()
  </code></pre>
  
  <p>Once <code>tornado.ioloop.IOLoop.instance().start()</code> is called, it blocks the program (or current thread). Reading the <a href="https://github.com/facebook/tornado/blob/master/tornado/ioloop.py#L288">source code</a> for the <code>IOLoop</code> object gives this example in the documentation for the <code>stop</code> function:</p>
  
  <pre><code>To use asynchronous methods from otherwise-synchronous code (such as
  unit tests), you can start and stop the event loop like this:
    ioloop = IOLoop()
    async_method(ioloop=ioloop, callback=ioloop.stop)
    ioloop.start()
  ioloop.start() will return after async_method has run its callback,
  whether that callback was invoked before or after ioloop.start.
  </code></pre>
  
  <p>However, I have no idea how to integrate this into my program. I actually have a class that encapsulates the web server (having it's own <code>start</code> and <code>stop</code> functions), but as soon as I call start, the program (or tests) will of course block anyway.</p>
  
  <p>I've tried to start the web server in another process (using the <code>multiprocessing</code> package). This is the class that is wrapping the web server:</p>
  
  <pre><code>class Server:
      def __init__(self, port=8888):
          self.application = tornado.web.Application([ (r"/", Handler) ])
  
          def server_thread(application, port):
              http_server = tornado.httpserver.HTTPServer(application)
              http_server.listen(port)
              tornado.ioloop.IOLoop.instance().start()
  
          self.process = Process(target=server_thread,
                                 args=(self.application, port,))
  
      def start(self):
          self.process.start()
  
      def stop(self):
          ioloop = tornado.ioloop.IOLoop.instance()
          ioloop.add_callback(ioloop.stop)
  </code></pre>
  
  <p>However, stop does not seem to entirely stop the web server since it is still running in the next test, even with this test setup:</p>
  
  <pre><code>def setup_method(self, _function):
      self.server = Server()
      self.server.start()
      time.sleep(0.5)  # Wait for web server to start
  
  def teardown_method(self, _function):
      self.kstore.stop()
      time.sleep(0.5)
  </code></pre>
  
  <p>How can I start and stop a Tornado web server from within a Python program?</p>