1. cherrypy
  2. CherryPy
Issue #1100 resolved

CherryPy 3.2.2 gives Engine ERROR when binding to while loopback disabled

created an issue

While trying CherryPy 3.2.2 on heroku.com free account (with Python 2.7.2), I encountered sudden crashs of my HelloWorld app after some time.

heroku forbids bindung to loopback device (localhost). I could reproduce this behaviour with disabling my loopback device and then starting my app locale bound to host

At first it was working well, but after a short wihle the error was thrown and the app crashed.

[[http://stackoverflow.com/questions/767575/cherrypy-hello-world-error/3282264#3282264|Here]] someone suggests it might be the [[http://docs.cherrypy.org/stable/refman/process/servers.html?highlight=wait_for_occupied_port#cherrypy.process.servers.wait_for_occupied_port|wait_for_occupied_port]] function that assumes that loopback is always available and therefore fails.

This is a log from these tests with disabled lo-device: {{{ [28/Oct/2011:21:56:49] ENGINE Listening for SIGHUP. [28/Oct/2011:21:56:49] ENGINE Listening for SIGTERM. [28/Oct/2011:21:56:49] ENGINE Listening for SIGUSR1. [28/Oct/2011:21:56:49] ENGINE Bus STARTING [28/Oct/2011:21:56:49] ENGINE Started monitor thread '_TimeoutMonitor'. [28/Oct/2011:21:58:30] ENGINE Error in 'start' listener <bound method Server.start of <cherrypy._cpserver.Server object at 0x8520c0c>> Traceback (most recent call last): File "/build/cherrypy/test/lib/python2.7/site-packages/cherrypy/process/wspbus.py", line 197, in publish output.append(listener(args, *kwargs)) File "/build/cherrypy/test/lib/python2.7/site-packages/cherrypy/_cpserver.py", line 151, in start ServerAdapter.start(self) File "/build/cherrypy/test/lib/python2.7/site-packages/cherrypy/process/servers.py", line 174, in start self.wait() File "/build/cherrypy/test/lib/python2.7/site-packages/cherrypy/process/servers.py", line 214, in wait wait_for_occupied_port(host, port) File "/build/cherrypy/test/lib/python2.7/site-packages/cherrypy/process/servers.py", line 427, in wait_for_occupied_port raise IOError("Port %r not bound on %r" % (port, host)) IOError: Port 5050 not bound on ''

[28/Oct/2011:21:58:30] ENGINE Shutting down due to error in start listener: Traceback (most recent call last): File "/build/cherrypy/test/lib/python2.7/site-packages/cherrypy/process/wspbus.py", line 235, in start self.publish('start') File "/build/cherrypy/test/lib/python2.7/site-packages/cherrypy/process/wspbus.py", line 215, in publish raise exc ChannelFailures: IOError("Port 5050 not bound on ''",)

[28/Oct/2011:21:58:30] ENGINE Bus STOPPING [28/Oct/2011:21:58:30] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('', 5050)) already shut down [28/Oct/2011:21:58:30] ENGINE Stopped thread '_TimeoutMonitor'. [28/Oct/2011:21:58:30] ENGINE Bus STOPPED [28/Oct/2011:21:58:30] ENGINE Bus EXITING [28/Oct/2011:21:58:30] ENGINE Bus EXITED }}}

Comments (8)

  1. Anonymous

    This is because on heroku you're not able to run on any port. Each dyno you run in gives you a PORT variable which you may bind your application to. To run on heroku you simply need to add:

    cherrypy.config.update({'server.socket_host': '',}) cherrypy.config.update({'server.socket_port': int(os.environ.get('PORT', '5000')),})

  2. Anonymous

    Were you actually able to use that code to get cherrypy running on heroku for more than a few minutes? It works for me for a minute or so and then crashes with vargo_hoat's error.

  3. vargo_hoat reporter

    to get it running was not the problem, the ports were assigned successfully. the problem ist the crashing after a minute or two. and this originates in the assumption of cherrypy's wait_for_occupied_port function that there is always a loopback device.

  4. Brandon Rhodes

    To be more specific, the assumption is built into the client_host() function in cherrypy/process/servers.py which even kind-of mentions the assumption in a comment:

    def client_host(server_host):
        """Return the host on which a client can connect to the given listener."""
        if server_host == '':
            # is INADDR_ANY, which should answer on localhost.
            return ''

    The solution, I believe, is to entirely disable the self-consistency check that CherryPy makes to see if the “ready” HTTP Server is truly ready. I am not entirely sure why, having seen the ready-flag appear, CherryPy feels it needs to make extra-sure that the port is really opened. Perhaps because of some obscure bug encountered once upon a time on a terrible operating system of some sort?

    In any event, the fix is easy.

    To make CherryPy work on Heroku today simply add this monkey-patch to your application's startup code:

            from cherrypy.process import servers
            def fake_wait_for_occupied_port(host, port): return
            servers.wait_for_occupied_port = fake_wait_for_occupied_port
  5. Log in to comment