Why asynchronous function in tornado is blocking?
Why incoming request are not being processed while another request is in the "waiting" state?
If you look at the code below, function "get" has a tornado task which is executed with "yield" keyword, which would mean "wait for a callback to be executed". In my code, the callback is never executed. If you run request second time, while first is on hold, the second request is not processed. If you run any other requests, they are being processed just fine.
So, my actions: 1. Start application 2. GET localhost:8080/ - Application is printing output "incoming call" 3. GET localhost:8080/anotherrequest - Application is printing output "another request" 4. GET localhost:8080/ - Application is not printing any output while I'm expecting it to print "incoming call". Why?
So, why this piece of code gets blocking? Code sample is attached.
I was using tornado 2.1 and python 2.7 to run this sample.
import tornado import tornado.web from tornado import gen class AnotherHandler(tornado.web.RequestHandler): @tornado.web.asynchronous def get(self): print 'another request' self.finish() class MainHandler(tornado.web.RequestHandler): def printStuff(*args, **kwargs): print 'incoming call' @tornado.web.asynchronous @tornado.gen.engine def get(self): result = yield tornado.gen.Task(self.printStuff); application = tornado.web.Application([ (r"/", MainHandler), (r"/anotherrequest", AnotherHandler) ]) if __name__ == "__main__": application.listen(8080) tornado.ioloop.IOLoop.instance().start()
Each new request to "localhost:8080/" will, in fact, cause your application to print "incoming call." However, requests to "localhost:8080/" will never finish. In order for the yield statement to be used, printStuff has to accept a callback and execute it. Also, an asynchronous get function must call self.finish:
class MainHandler(tornado.web.RequestHandler): def printStuff(self, callback): print 'incoming call' callback() @tornado.web.asynchronous @tornado.gen.engine def get(self): result = yield tornado.gen.Task(self.printStuff) self.finish()
It's easier to use Tornado's modern "coroutine" interface instead of gen.Task and gen.engine:
class MainHandler(tornado.web.RequestHandler): @gen.coroutine def printStuff(self): print 'incoming call' @gen.coroutine def get(self): result = yield self.printStuff() self.finish()
Found the problem, it's actually happening when requests are made from the browser. With "curl" everything works as expected. Sorry for inconvenience.