CherryPy 3.2.2 gives Engine ERROR when binding to 0.0.0.0 while loopback disabled

vargo_hoat avatarvargo_hoat 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 0.0.0.0:5000.

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

Here someone suggests it might be the 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 '0.0.0.0'

[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 '0.0.0.0'",)

[28/Oct/2011:21:58:30] ENGINE Bus STOPPING
[28/Oct/2011:21:58:30] ENGINE HTTP Server cherrypy._cpwsgi_server.CPWSGIServer(('0.0.0.0', 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': '0.0.0.0',}) 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

    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 == '0.0.0.0':
            # 0.0.0.0 is INADDR_ANY, which should answer on localhost.
            return '127.0.0.1'
       ...
    

    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
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.