Skip to content

std: Use getexecpath() for current_exe() on OpenBSD - #163393

Open
brad0 wants to merge 1 commit into
rust-lang:mainfrom
brad0:std_src_sys_paths_unix
Open

brad0 wants to merge 1 commit into
rust-lang:mainfrom
brad0:std_src_sys_paths_unix

Conversation

@brad0

@brad0 brad0 commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

OpenBSD added getexecpath(3) to libc, which returns an
already-canonicalized executable path directly. Replace the
sysctl(KERN_PROC_ARGV)-based implementation.

This was the last user of div_exact in std, so drop the
exact_div feature gate.

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Sep 27, 2026
@rustbot

rustbot commented Sep 27, 2026

Copy link
Copy Markdown
Collaborator

r? @JohnTitor

rustbot has assigned @JohnTitor.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @ChrisDenton, libs
  • @ChrisDenton, libs expanded to 13 candidates
  • Random selection from 7 candidates

@brad0

brad0 commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor Author

Just waiting for libc 0.2.191.

brad0 referenced this pull request in fish-shell/fish-shell Sep 27, 2026
OpenBSD 8.0 adds getexecpath(3), which returns the absolute path
to the current executable. Prefer it over std::env::current_exe(),
which has no reliable implementation on OpenBSD.

In future, std::env::current_exe() should do the same under the hood,
but this is blocked on rust-lang/rust#161000.

Fixes #9086
@brad0
brad0 force-pushed the std_src_sys_paths_unix branch from b30a2cb to 4dc700e Compare October 4, 2026 11:04
@rustbot

This comment has been minimized.

OpenBSD added getexecpath(3) to libc, which returns an
already-canonicalized executable path directly. Replace the
sysctl(KERN_PROC_ARGV)-based implementation.

This was the last user of div_exact in std, so drop the
exact_div feature gate.
@brad0
brad0 force-pushed the std_src_sys_paths_unix branch from 335f67b to 5fbbf47 Compare October 19, 2026 07:20
@rustbot

rustbot commented Oct 19, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@brad0

brad0 commented Oct 19, 2026

Copy link
Copy Markdown
Contributor Author

@semarie

@semarie

semarie commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

Just a question : any particular reason to diverge from the patch currently used downstream ? see lang/rust/patches/patch-library_std_src_sys_paths_unix_rs

@kpcyrd

kpcyrd commented Oct 19, 2026 •

Copy link
Copy Markdown

@semarie from how I'm reading the code, the downstream code does one extra heap allocation.

The downstream one does:

  • allocate libc::PATH_MAX bytes on the heap (len == capacity)
  • lets the kernel write data to this address
  • takes a slice from that heap allocation (from address to first null byte)
  • uses OsStr::from_bytes to get a "Borrowed reference to an OS string" (which has a life-time dependency on the first heap allocation)
  • uses PathBuf::from with From<OsStr> to copy the bytes from that slice into a new, second heap allocation (resolving the life-time dependency on the first allocation, which can now be safely freed)

The one suggested here does:

  • allocate libc::PATH_MAX bytes on the heap (len == capacity)
  • lets the kernel write data to this address
  • counts the bytes until the first null byte and then adjusts len accordingly
  • uses OsString::from_vec to pass ownership of the vec to an OsString, which owns it's own data, without a life-time dependency
  • uses PathBuf::from with From<OsString> to pass ownership of that OsString to the PathBuf

Due to type-erasure during compile, the last two steps in the later approach are effectively no-ops at runtime, if I'm not mistaken.

let len = CStr::from_ptr(path.as_ptr().cast()).count_bytes();
path.truncate(len);
}
Ok(PathBuf::from(OsString::from_vec(path)))

@catap catap Oct 19, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Probably I've missed why do we need truncate here. I think it should be as simple as:

    let mut path = vec![0; libc::PATH_MAX as usize];
    unsafe {
        cvt(getexecpath(path.as_mut_ptr(), path.len()))?;
        let path = CStr::from_ptr(path.as_ptr()).to_bytes();
        Ok(PathBuf::from(OsStr::from_bytes(path)))
    }

View changes since the review

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This code does two heap allocations instead of just one, see this comment: #163393 (comment)

@brad0

brad0 commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author
  • It uses the libc binding instead of a local extern block.
  • It avoids a second allocation: the buffer is truncated at the NUL
    and handed to OsString::from_vec, rather than borrowing it as an
    &OsStr and copying it into a new PathBuf. This matches the
    FreeBSD/NetBSD/Apple current_exe() implementations in the
    same file.
  • With the sysctl/argv code gone, nothing in std uses div_exact any
    more, so #![feature(exact_div)] is dropped.

@semarie semarie left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@brad0

brad0 commented Nov 2, 2026

Copy link
Copy Markdown
Contributor Author

@JohnTitor Ping.

@JohnTitor JohnTitor left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry for the delay! LGTM @bors r+

View changes since this review

@rust-bors

rust-bors Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 5fbbf47 has been approved by JohnTitor

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 3, 2026
@brad0

brad0 commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

@JohnTitor Thanks!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants