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
fix: unix socket support multi workers #433
fix: unix socket support multi workers #433
Conversation
55958e7
to
d80dc4a
Compare
d80dc4a
to
221c76a
Compare
sock = config.bind_unix_socket() | ||
supervisor.run(server.run, sockets=[sock]) | ||
sock.close() | ||
os.remove(config.uds) |
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.
Curious: Why do we remove the UDS socket here?
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.
From man 7 Unix
Binding to a socket with a filename creates a socket in the filesystem that must be deleted by the caller when it is no longer needed (using unlink(2)). The usual UNIX close-behind semantics apply; the socket can be unlinked at any time and will be finally removed from the filesystem when the last reference to it is closed.
I think there is another problem. If our process crashes, os.remove()
will not be called and we’ll have a dangling socket. It seems that we need to check the socket file before bind()
.
Why haven’t encountered this problem when use one worker and unix socket mode?
Because we use the create_unix_server
Lines 363 to 373 in e0a77de
elif config.uds is not None: | |
# Create a socket using UNIX domain socket. | |
uds_perms = 0o666 | |
if os.path.exists(config.uds): | |
uds_perms = os.stat(config.uds).st_mode | |
server = await loop.create_unix_server(create_protocol, path=config.uds) | |
os.chmod(config.uds, uds_perms) | |
message = "Uvicorn running on unix socket %s (Press CTRL+C to quit)" | |
self.logger.info(message % config.uds) | |
self.servers = [server] | |
create_unix_server
will unlink the socket file before it starts.
info = transport.get_extra_info("peername") | ||
if info is not None and isinstance(info, (list, tuple)) and len(info) == 2: | ||
return (str(info[0]), int(info[1])) | ||
return None |
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.
Is there a reason why we're changing the None
case here?
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.
None
was displayed in access log.
2019-10-08 15:47:52,870 - INFO - None - "GET / HTTP/1.1" 200
2019-10-08 15:48:00,546 - INFO - None - "GET / HTTP/1.1" 200
2019-10-08 15:48:01,285 - INFO - None - "GET / HTTP/1.1" 200
Or we can fix here
diff --git a/uvicorn/protocols/http/httptools_impl.py b/uvicorn/protocols/http/httptools_impl.py
index 2e1dd90..8b414b2 100644
--- a/uvicorn/protocols/http/httptools_impl.py
+++ b/uvicorn/protocols/http/httptools_impl.py
@@ -436,7 +436,7 @@ class RequestResponseCycle:
if self.access_log:
self.logger.info(
'%s - "%s %s HTTP/%s" %d',
- self.scope["client"],
+ self.scope["client"] or "-",
self.scope["method"],
get_path_with_query_string(self.scope),
self.scope["http_version"],
Any good idea, thanks?
I just bumped into this today, as well. I can use TCP for now, but would love to help out here if I can. |
really needed |
Emm, I will fix the conflicts recently. |
Both the issue I had #586 and the Issue #722 could also be solved by using the fix proposed in this pull request. |
I'll close this PR, as #1009 addressed the issue that motivated it. |
None
remote addr in access log.