Allow devserver to bind to any available port.
Users can now start the devserver with --port=0 and have it bind to any
available port. They can further use --portfile and have it dump the
said port to a file (analogously to --pidfile).
This is done by adding a new module (cherrypy_ext) that consists of two
separate but related components:
1) A class for patching CherryPy's so it can start with
server.socket_port == 0, making it bind to an arbitrary available
port. To achieve this, we wrap two module-level functions meant to
wait for a port to become either free or occupied, so that they can
do their intended work even when called with port == 0. In essence,
we use the same logic from the above plugin to pull the actual port
number from the HTTP server. Wrapping of these two functions is,
too, compatible with all the relevant CherryPy versions; it will fail
hard (AttributeError) if these functions are not present.
2) A new CherryPy plugin (PortFile) for writing the bound port to
a given file. While somewhat hacky, this is based on fairly solid
assumptions about the hierarchy of the HTTP server properties, as
well as the publishing of some (any) signals after a server has
started. It is compliant with a multitude of CherryPy versions from
the chroot version to CherryPy's dev ToT.
The advantages of this approach are the following:
* It is forward-compatible, making minimal (and mostly reasonable)
assumptions about CherryPy's architecture and inner workings. The
wait-for-port wrapping logic will fail the devserver if these
assumptions are breached.
* It is minimally invasive, as all new logic is implemented outside of
CherryPy and will have no effect if CherryPy is started as before
(namely, with a non-zero port).
Disadvantages are as follows; note that there is an upstream patch to
CherryPy that's pending approval that addresses all of these:
* When started with a zero port, CherryPy will unfortunately report that
it is 'Serving on host:0', instead of the actual port number. It is
necessary to make changes to ServerAdapter to make it report the
actual port.
* It is not meant for use, and will actually fail, if CherryPy is
configured to run multiple HTTP servers. Since this isn't the intended
mode of use in devserver, we don't expect this to be a problem.
* In general, it violates an implicit invariant in CherryPy, whereas the
bind_addr property of the server object reflects the actual name of
the socket used by the underlying HTTP server, once bound. This is no
longer the case, and fixing this requires changes to the ServerAdapter
class, as well as the underlying HTTP server implementation.
BUG=chromium:322436
TEST=devserver starts with --port=0; writes port to --portfile.
Change-Id: I40fc54a547ebde83138daf7a4014a54741b712a3
Reviewed-on: https://chromium-review.googlesource.com/185700
Reviewed-by: Gilad Arnold <[email protected]>
Commit-Queue: Gilad Arnold <[email protected]>
Tested-by: Gilad Arnold <[email protected]>
3 files changed