-
Notifications
You must be signed in to change notification settings - Fork 1.8k
fix: use SO_EXCLUSIVEADDRUSE on Windows for callback server #18137
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -59,6 +59,9 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from random import SystemRandom | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from string import ascii_letters, digits | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import socket | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import sys | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import webbrowser | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import wsgiref.simple_server | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import wsgiref.util | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -432,10 +435,15 @@ def run_local_server( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| authorization server. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| wsgi_app = _RedirectWSGIApp(success_message) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Fail fast if the address is occupied | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Fail fast if the address/port is occupied | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| wsgiref.simple_server.WSGIServer.allow_reuse_address = False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Use _ExclusiveWSGIServer so that other apps cannot bind to the same address/port on Windows. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| local_server = wsgiref.simple_server.make_server( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bind_addr or host, port, wsgi_app, handler_class=_WSGIRequestHandler | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bind_addr or host, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| port, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| wsgi_app, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| server_class=_ExclusiveWSGIServer, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handler_class=_WSGIRequestHandler, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -478,6 +486,21 @@ def run_local_server( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self.credentials | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class _ExclusiveWSGIServer(wsgiref.simple_server.WSGIServer): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Custom WSGIServer. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Enforces exclusive address binding on Windows. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Setting `WSGIServer.allow_reuse_address` is not enough, since it sets `SO_REUSEADDR` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| and not `SO_EXCLUSIVEADDRUSE`. `SO_REUSEADDR` alone allows other processes to bind | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| to the same address and port on Windows. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def server_bind(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if sys.platform == "win32" and hasattr(socket, "SO_EXCLUSIVEADDRUSE"): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| super().server_bind() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+489
to
+501
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To avoid modifying the global On Windows, if
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class _WSGIRequestHandler(wsgiref.simple_server.WSGIRequestHandler): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Custom WSGIRequestHandler. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modifying the global class attribute
wsgiref.simple_server.WSGIServer.allow_reuse_addressis risky because it mutates the behavior of the standard library'sWSGIServerglobally for the entire Python process. This can lead to unexpected side effects in other parts of the application or other libraries that rely on the default behavior ofWSGIServer.Since we are now using a custom subclass
_ExclusiveWSGIServer, we can defineallow_reuse_address = Falsedirectly as a class attribute on_ExclusiveWSGIServer. This achieves the same "fail fast" behavior locally without global side effects.