-
-
Notifications
You must be signed in to change notification settings - Fork 193
Fix 2-second systemd notify stalls in cloud-hypervisor #493
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 | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -126,6 +126,45 @@ let | |||||||
| vulkan = true; | ||||||||
| }; | ||||||||
|
|
||||||||
| # A proxy that forwards systemd notifications from cloud-hypervisor's vsock socket. It | ||||||||
| # intentionally calls read only once and closes the connection immediately, which unblocks the | ||||||||
| # guest's blocking recv() (systemd does shutdown(SHUT_WR) + recv() as an | ||||||||
| # end-of-message handshake in sd-daemon.c, but cloud-hypervisor does not propagate the half-close | ||||||||
| # to the host-side Unix socket). | ||||||||
| # | ||||||||
| # Previously, this used socat with a 2-second timeout but this causes systemd to stall on every | ||||||||
| # notification, causing extremely slow boot times. | ||||||||
| # | ||||||||
| # An important caveat is that the message could theoretically be truncated but this should not | ||||||||
| # happen in practice unless the message is large (systemd notifications are small). | ||||||||
| # | ||||||||
| # TODO(rzhikharevich): Ideally, cloud-hypervisor should propagate the half-close, then the | ||||||||
| # theoretical truncation risk could be fixed by closing the connection after detecting it. | ||||||||
| vsockNotifyProxy = pkgs.writers.writePython3Bin "vsock-notify-proxy" {} '' | ||||||||
| import asyncio | ||||||||
| import os | ||||||||
| import socket | ||||||||
SuperSandro2000 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
|
|
||||||||
| notify_socket = os.environ["NOTIFY_SOCKET"] | ||||||||
| notify = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) | ||||||||
|
|
||||||||
|
|
||||||||
| async def handle(reader, writer): | ||||||||
| data = await reader.read(65536) | ||||||||
SuperSandro2000 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||
| writer.close() | ||||||||
|
||||||||
| writer.close() | |
| writer.close() | |
| await writer.wait_closed() |
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.
The 1st example in the Python asyncio documentation does this, too.
SuperSandro2000 marked this conversation as resolved.
Show resolved
Hide resolved
SuperSandro2000 marked this conversation as resolved.
Show resolved
Hide resolved
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.
| path = os.environ["VSOCK_NOTIFY_PATH"] | |
| server = await asyncio.start_unix_server(handle, path=path) | |
| server = await asyncio.start_unix_server(handle, path=sys.argv[0]) |
We can make this kinda dirty here, as we control all invocations and this fails loudly when no arg is there, os.environ does IIRC return empty string.
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.
| VSOCK_NOTIFY_PATH=${vsockPath}_8888 ${vsockNotifyProxy}/bin/vsock-notify-proxy & | |
| ${lib.getExe vsockNotifyProxy} ${vsockPath}_8888 & |
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.