Repository navigation
Conversation
| /// other name goes through the regular filesystem-backed encoding. | ||
| unsafe fn build_sockaddr(name: &str) -> Result<(sockaddr_un, usize), UnixError> { | ||
| #[cfg(target_os = "linux")] | ||
| if let Some(abstract_name) = name.strip_prefix('@') { |
There was a problem hiding this comment.
On linux, how can abstract_name starts with anything other than @? If so, what's the point of the @ prefix convention?
There was a problem hiding this comment.
Fair point. To clarify:
build_sockaddr is intentionally a generic utility rather than something coupled to OsIpcOneShotServer::new() / make_abstract_name(). The current PR is the only caller, and yes, on Linux it currently always passes @-prefixed names.
The @ prefix is simply the user-space convention used here to distinguish abstract socket names from filesystem-backed paths:
@name→ Linux abstract namespacename→ regular filesystem-backed socket
This convention is also commonly used by tools such as systemd, socat, and ss to represent abstract sockets; it corresponds to sun_path[0] == 0.
On non-Linux platforms, names go through the existing filesystem-path encoding unchanged.
There was a problem hiding this comment.
Thanks for the clarification. Some developers regard dead code as technical debt. Maybe a comment in the code is warranted, but I won't insist.
There was a problem hiding this comment.
@miruji Please note that I am not a maintainer of this project, so I defer to maintainers to set coding standards etc. However, should you wish to adopt my suggestion to remove the technical debt, the steps are to:
- Not prefix the path returned from
make_abstract_namewith@(e.g. changeformat!("@ipc-osn-{hex}")toformat!("ipc-osn-{hex}")). - Change the linux code in
build_sockaddrto usename(rather thanabstract_name) and delete the test for the@prefix. (You may wish to replace theifstatement with a{}block so it can be compiled for linux only.) - Fix up the comments to match the above changes.
So, on Linux, build_sockaddr is passed the return value of make_abstract_name without the prefix @ convention.
Note: since I am not a maintainer, I cannot approve/merge this PR, but hopefully someone else will.
There was a problem hiding this comment.
I’ve made the changes you pointed out.
And don’t worry, I understand that you’re not a maintainer. I just wanted to say that I really do take your feedback into account.
If I were doing this for myself, I would probably do quite a few things differently. So it’s completely fine that we’re adapting the code to fit the project.
As a contributor, you have every right to review the PR and suggest changes, which is exactly what you did, and I appreciate that.
I left all three commits separate so that the development process is visible. When merging into the main branch, they should be squashed into a single commit to keep the history clean.
I’ve tested it again, and everything works perfectly without any further changes.
There was a problem hiding this comment.
Thanks. Those changes look good to me.
| for (i, b) in bytes.iter().enumerate() { | ||
| sockaddr.sun_path[i + 1] = *b as c_char; | ||
| } |
There was a problem hiding this comment.
According to https://www.man7.org/linux/man-pages/man2/connect.2.html, sun_path is a null-terminated string for AF_UNIX sockets (at least for portable programs), so adding bytes after the null seems strange.
There was a problem hiding this comment.
Thanks for the review. The null-termination requirement in connect(2) applies to pathname sockets. For abstract sockets, man 7 unix (https://man7.org/linux/man-pages/man7/unix.7.html) says they are distinguished by sun_path[0] being a null byte, and the address is given by the additional bytes covered by the address length.
So here sun_path[0] is a marker, not a terminator: the kernel reads the name using addrlen (sizeof(sa_family_t) + 1 + name.len()), not strlen. The branch is gated by #[cfg(target_os = "linux")], so other platforms never reach it.
I added comments explaining this in e75cee3.
glyn
left a comment
There was a problem hiding this comment.
Thanks for the latest changes. Looks good to me. (It seems I can approve after all.)
|
Yes, I also just mentioned this in my chillffi framework, where I originally discovered this issue. I did this now so that it is already fixed on my side while this is still being accepted here. And also because I have quite a lot of tests on Linux, macOS, and Windows, and my FFI is very heavily tied to I mean this to say that everything works for me. This is just additional confirmation that nothing has been broken. I also checked this in those limited environments I mentioned, and there is no issue there either. |
OsIpcOneShotServer::new()currently requires a writable temp directory (viatempfile::Builder::tempdir()) purely to obtain a filesystem path for the bootstrap unix socket.On Linux, this is unnecessary: the abstract socket namespace lets us bind/connect without touching the filesystem at all.
This PR switches the one-shot server to an abstract-namespace address on Linux only.
Non-Linux platforms are untouched (
#[cfg(not(target_os = "linux"))]keeps the original tempdir-based path).The public API is unchanged — the returned "name" is still an opaque
Stringhanded toconnect(), exactly as documented; nothing about its format was ever part of the contract.Motivation: in containers/sandboxes where
/tmpis read-only or otherwise unwritable,tempdir()fails with aPermissionDenied-styleio::Errorthat carries noraw_os_error()(it's wrapped bytempfilein aPathError).That trips the
assert!(e.kind() == ConnectionReset)inFrom<io::Error> for UnixError, causing a hard panic instead of a recoverable error — this happens today for any consumer bootstrapping viaIpcOneShotServerin such an environment.This PR removes the precondition entirely rather than handling the error more gracefully.