Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite WerkzeugServer for better IPv4/v6 handling #1449

Merged
merged 6 commits into from
Sep 21, 2018

Conversation

nfelt
Copy link
Contributor

@nfelt nfelt commented Sep 20, 2018

This rewrites the WerkzeugServer wrapper introduced in #1409 to eliminate some issues with the old approach to IPv4/v6 handling and in particular fix #1320. Gory details are in #1320 (comment)

This change also streamlines the class so that it now directly inherits from Werkzeug's ThreadedWSGIServer class, which gives us a serve_forever() implementation for free and cleans up the handle_error() behavior so it's an overridden method instead of monkey-patched.

Fixes #1320

Copy link
Contributor

@stephanwlee stephanwlee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing a deep dive and fixing the issue once and for all!

Seems like a test is failing:

ERROR: testSpecifiedHost (__main__.WerkzeugServerTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/travis/.bazel-output-
...
OSError: [Errno 99] Cannot assign requested address


def serve_forever(self):
self._server.serve_forever()
def _get_wildcard_address(self, port):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you rename this method to _get_wildcard_host?

It seems like word address has been conflated.

>>> wildcard_addrs = socket.getaddrinfo(
            None, port, socket.AF_UNSPEC, socket.SOCK_STREAM,
            socket.IPPROTO_TCP, socket.AI_PASSIVE)
<<< [(30, 1, 6, ('::', 6006, 0, 0))]

from what I can tell, the sockaddr in L318 refers to <host, port, ?, ?> tuple and in L322, we seem to be returning only the host part.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'd prefer to stick with "address". IMO "wildcard host" doesn't really make sense because 0.0.0.0 isn't a hostname and no host actually has that IP address.

Unfortunately this terminology is just a bit confusing - "socket address" typically does include the IP address as well as a port: https://en.wikipedia.org/wiki/Network_socket#Socket_addresses

I've reworded the rest of the function body though to be a bit clearer, so now I name the return value "addrinfos" instead of "wildcard_addrs" and added a comment to clarify the sockaddr part as a socket address.

msg = (
'TensorBoard attempted to bind to port %d, but it was already in use'
% port)
raise
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be in-familiarity but what does this do and how does it relate to L298?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revised this to be clearer about the control flow

tensorboard/program.py Show resolved Hide resolved
Copy link
Contributor Author

@nfelt nfelt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PTAL, made some changes as well as better error handling that I hope should fix the Travis failure.

tensorboard/program.py Show resolved Hide resolved
msg = (
'TensorBoard attempted to bind to port %d, but it was already in use'
% port)
raise
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revised this to be clearer about the control flow


def serve_forever(self):
self._server.serve_forever()
def _get_wildcard_address(self, port):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'd prefer to stick with "address". IMO "wildcard host" doesn't really make sense because 0.0.0.0 isn't a hostname and no host actually has that IP address.

Unfortunately this terminology is just a bit confusing - "socket address" typically does include the IP address as well as a port: https://en.wikipedia.org/wiki/Network_socket#Socket_addresses

I've reworded the rest of the function body though to be a bit clearer, so now I name the return value "addrinfos" instead of "wildcard_addrs" and added a comment to clarify the sockaddr part as a socket address.

@stephanwlee
Copy link
Contributor

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fails silently if port is occupied
2 participants