Skip to content
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

Add __errno_location on Redox, DragonFlyBSD, Haiku #1432

Merged
merged 6 commits into from
Jul 15, 2019

Conversation

josephlr
Copy link
Contributor

@josephlr josephlr commented Jul 9, 2019

Currently libstd and the getrandom crate have to use external declarations in order to implement errno_location across all UNIX platforms. This change adds bindings for the remaining UNIX platforms, allowing everyone to just use normal libc bindings.

This also removes the need for a seperate errno-dragonfly crate.

Links to the relevant header files:

  • Redox: relibc's bits/errno.h uses __errno_location
  • Haiku: posix/errno.h uses _errnop
  • DragonFlyBSD: sys/errno.h uses __error just like FreeBSD (which makes sense)
    • Note that the __error function is inlined. I don't think this causes a problem.

@rust-highfive
Copy link

r? @gnzlbg

(rust_highfive has picked a reviewer for you, use r? to override)

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 9, 2019

@bors: r+

Thanks!

@bors
Copy link
Contributor

bors commented Jul 9, 2019

📌 Commit 4fc38ca has been approved by gnzlbg

@bors
Copy link
Contributor

bors commented Jul 9, 2019

⌛ Testing commit 4fc38ca with merge acd8db5...

bors added a commit that referenced this pull request Jul 9, 2019
Add __errno_location on Redox, DragonFlyBSD, Haiku

Currently [`libstd`](https://github.com/rust-lang/rust/blob/909f5a049415a815b23502a5498de9a99bbf276b/src/libstd/sys/unix/os.rs#L29-L49) and the [`getrandom` crate](https://github.com/rust-random/getrandom/pull/54/files#diff-027a56068e2bf3d31dc4273ee6e07034R12) have to use external declarations in order to implement `errno_location` across all UNIX platforms. This change adds bindings for the remaining UNIX platforms, allowing everyone to just use normal `libc` bindings.

This also removes the need for a seperate [`errno-dragonfly`](https://crates.io/crates/errno-dragonfly) crate.

Links to the relevant header files:

- Redox: [`relibc`'s `bits/errno.h`](https://github.com/redox-os/relibc/blob/master/include/bits/errno.h) uses `__errno_location`
- Haiku: [`posix/errno.h`](https://github.com/luciang/haiku/blob/master/headers/posix/errno.h) uses `_errnop`
- DragonFlyBSD: [`sys/errno.h`](https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/errno.h) uses `__error` just like FreeBSD (which makes sense)
  - Note that the `__error` function is inlined. I don't think this causes a problem.
@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 9, 2019

@bors: r-

The paths need fixing.

@bors
Copy link
Contributor

bors commented Jul 9, 2019

💔 Test failed - checks-travis

@josephlr
Copy link
Contributor Author

josephlr commented Jul 9, 2019

The paths need fixing.

Copy paste bites again, should be fixed now.

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 9, 2019

Thanks! @bors: r+

@bors
Copy link
Contributor

bors commented Jul 9, 2019

📌 Commit e9c1ade has been approved by gnzlbg

@bors
Copy link
Contributor

bors commented Jul 9, 2019

⌛ Testing commit e9c1ade with merge d829520...

bors added a commit that referenced this pull request Jul 9, 2019
Add __errno_location on Redox, DragonFlyBSD, Haiku

Currently [`libstd`](https://github.com/rust-lang/rust/blob/909f5a049415a815b23502a5498de9a99bbf276b/src/libstd/sys/unix/os.rs#L29-L49) and the [`getrandom` crate](https://github.com/rust-random/getrandom/pull/54/files#diff-027a56068e2bf3d31dc4273ee6e07034R12) have to use external declarations in order to implement `errno_location` across all UNIX platforms. This change adds bindings for the remaining UNIX platforms, allowing everyone to just use normal `libc` bindings.

This also removes the need for a seperate [`errno-dragonfly`](https://crates.io/crates/errno-dragonfly) crate.

Links to the relevant header files:

- Redox: [`relibc`'s `bits/errno.h`](https://github.com/redox-os/relibc/blob/master/include/bits/errno.h) uses `__errno_location`
- Haiku: [`posix/errno.h`](https://github.com/luciang/haiku/blob/master/headers/posix/errno.h) uses `_errnop`
- DragonFlyBSD: [`sys/errno.h`](https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/errno.h) uses `__error` just like FreeBSD (which makes sense)
  - Note that the `__error` function is inlined. I don't think this causes a problem.
@bors
Copy link
Contributor

bors commented Jul 9, 2019

💔 Test failed - status-appveyor

@BurntSushi
Copy link
Member

Note that both std and errno-dragonfly seem to implement this differently than what's in this PR for Dragonfly. Was that intentional?

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 9, 2019

cc @strangelittlemonkey - could you review the dragonfly impl ?

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 9, 2019

cc @sikmir could you review this for haiku?
cc @jackpot51 could you review this for redox ?

@josephlr
Copy link
Contributor Author

josephlr commented Jul 9, 2019

Note that both std and errno-dragonfly seem to implement this differently than what's in this PR for Dragonfly. Was that intentional?

This was intentional. Implementing errno with a #[thread_local] would be slightly more efficient (as you don't have a function call). However, that's not possible on stable Rust, so using the function instead seems like the best bet.

The only difference between DragonFlyBSD an all the other UNIXes is that __error declared as:

static __inline int *__error(void) { ... }

in the header file (see the above link). I think Rust can handle such a function OK, but that could be the reason for the difference.

@BurntSushi
Copy link
Member

Interesting. The errno-dragonfly crate actually uses custom C code to return errno and then links to that. Is that just an oversight on their part?

N.B. I am speaking from ignorance here. I'm only asking these questions because I'm curious. :-)

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 10, 2019

I think Rust can handle such a function OK

The __error function is static (TU-private) and inline, so it probably isn't part of the generated binary, and we can't link against that. That is, we would need to implement it in this crate.

DragonflyBSD defines errno here as :

extern __thread int	errno;
static __inline int* __error() { return &errno; }

This:

extern __thread int	errno;
int* foo() { return &errno; }

emits:

define dso_local i32* @foo() #0 {
  ret i32* @errno
}

Notice the dso_local in there.


I think that in Rust we would need: extern "C" { #[thread_local] static errno: i32; } (using feature(thread_local)), but I don't know whether this currently works when used on extern statics. Right now we don't emit dso_local, and I don't know how important that is. cc @eddyb @rkruppe

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 10, 2019

Also cc @joshtriplett: there is no stable Rust way to link against extern #[thread_local] statics, that should probably be added to the list of missing features for C FFI.

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 10, 2019

@BurntSushi

Is that just an oversight on their part?

I don't think so. They can't create a pointer to the __thread int errno; from Rust, so they have to do that from C. See above.

@eddyb
Copy link
Member

eddyb commented Jul 10, 2019

dso_local is a function attribute and likely the static on foo.
You need to compare the declarations of the @errno global to check if the #[thread_local] works (it should, since we lower it pretty straightforwardly).

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 10, 2019

@eddyb so we lower the extern "C" { #[thread_local] static errno: i32; } to

@errno = external thread_local global i32

clang lowers this to:

@errno = external thread_local global i32, align 4

So I think #[thread_local] should work.

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 10, 2019

@josephlr we do have a cargo feature feature = "unstable" that you could use to only provide the #[thread_local]s for nightly users that enable that feature via a #[cfg()].

I don't think there is a pure Rust solution available for stable Rust users. Linking to a C snippet that returns a pointer to the thread local like the errno-dragonfly crate does feels like the simplest solution to this problem.

@eddyb
Copy link
Member

eddyb commented Jul 10, 2019

Could that platform's errno be gated by #[cfg(feature = "unstable")] to land this, and have an issue for stable support?

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 10, 2019

@eddyb sure, and libstd enables the "unstable" feature, so it can make use of this to simplify the implementation. The getrandom crate would need to wait a bit.

Copy link
Contributor

@jackpot51 jackpot51 left a comment

Choose a reason for hiding this comment

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

This is correct for Redox

Copy link
Contributor

@sikmir sikmir left a comment

Choose a reason for hiding this comment

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

LGTM

@josephlr
Copy link
Contributor Author

@josephlr we do have a cargo feature feature = "unstable" that you could use to only provide the #[thread_local]s for nightly users that enable that feature via a #[cfg()].

@gnzlbg that works, I’ll make the change to add __error and errno behind this guard. For getrandom, we might just be OK requiring nightly for DragonFlyBSD.

@josephlr
Copy link
Contributor Author

It turns out the CI is failing due to a transitive serde_derive dependency, which is breaking because of rust-lang/rust#62562

All the errors (as far as I can tell) are related to this bug, so the breakage is not caused by this PR.

@strangelittlemonkey
Copy link

strangelittlemonkey commented Jul 11, 2019 via email

@eddyb
Copy link
Member

eddyb commented Jul 11, 2019

@strangelittlemonkey "nightly" is misleading - what's important here is "unstable", which is allowed for any dependency of std/rustc.

Even if users of libc from crates.io might not use the unstable feature on DragonFlyBSD, to build any release of Rust, including stable/beta, std needs errno from libc, for which it can enable some "unstable" flag to provide errno.

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 11, 2019

@strangelittlemonkey or in other words, when the compiler is compiling itself, which is something that has to be done to build a compiler for DragonflyBSD, it can use unstable features that are generally only available on nightly.

@strangelittlemonkey
Copy link

strangelittlemonkey commented Jul 11, 2019 via email

@eddyb
Copy link
Member

eddyb commented Jul 12, 2019

I’m just saying requiring nightly to build it at all would make DragonFly a moot point, but allowing extra features if building with nightly would be different and fine

It's the latter, we're talking about an opt-in way to enable errno on DragonFly that requires unstable. This is either for nightly users or building Rust itself.

Like I said before, that opt-in would be enabled by std, which depends on this crate for its FFI to implement std::io, std::fs and other such functionality.

So when you build any future release of Rust (including stable ones) for DragonFlyBSD, the errno added here would be used, even if a use of that build of Rust wouldn't have that errno available.

So, yes, it's dead code for normal users of this crate, but would still be needed and used for the standard library (which does its OS FFI through this very same crate).

@josephlr
Copy link
Contributor Author

@gnzlbg rust-lang/rust#62562 has been fixed, so the CI is passing again

@strangelittlemonkey Nightly build issues aside, the code added in this PR is required to build libstd for DragonFlyBSD (not necessarily building on DragonFlyBSD). Will this code work for DragonFlyBSD? and if not, what should we do instead?

I updated the docs to point out why we need unstable at all

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 13, 2019

Just to triple check, is there any crate that wants to use this from crates.io ?

If not, then we don't need the unstable feature, and can just feature gate this using the "dep-of-std" feature.

@josephlr
Copy link
Contributor Author

josephlr commented Jul 13, 2019

Just to triple check, is there any crate that wants to use this from crates.io ?

Initially the thought was to also use this for getrandom, but due to rust-lang/cargo#4866 we can't reasonably turn on the unstable feature for only one target, so I don't know of any crates that currently want it.

If not, then we don't need the unstable feature, and can just feature gate this using the "dep-of-std" feature.

Sounds good, I'll make the change unless anyone else wants to use this.

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 13, 2019

@josephlr you can chime in in the thread_local tracking issue in rust-lang/rust, and mention that getrandom wants to use it. I don't know if anybody has needed to use extern thread-locals before, but that's something required for being able to FFI with C..

@BurntSushi
Copy link
Member

BurntSushi commented Jul 13, 2019

Just to triple check, is there any crate that wants to use this from crates.io ?

Yes. walkdir will eventually want this. I'm currently using the same hack as the errno-dragonfly crate in my branch: https://github.com/BurntSushi/walkdir/blob/ag/sys/src/os/unix/errno.rs (Which I'll have to continue using if errno on DragonFly is only available with nightly Rust.)

@josephlr
Copy link
Contributor Author

Just to triple check, is there any crate that wants to use this from crates.io ?

Yes. walkdir will eventually want this. I'm currently using the same hack as the errno-dragonfly crate in my branch: https://github.com/BurntSushi/walkdir/blob/ag/sys/src/os/unix/errno.rs (Which I'll have to continue using if errno on DragonFly is only available with nightly Rust.)

OK, as walkdir and getrandom can’t use this until it’s on stable, we don’t need the unstable feature. I’ll mention this on the main Rust tracking issue.

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 14, 2019

Looking at the tracking issue, and the thread_local! discussions, it appears that 1) thread_local! solves the problem for most people, and 2) the main uncertainty is that #[thread_local] isn't portable.

Maybe we could reduce the scope of an initial version of #[thread_local] to extern static declarations. If the target does not support #[thread_local], well then the extern static declaration is incorrect since there cannot be a definition anywhere, and using it would already be UB. We could add on top of this a "best effort" compilation error, e.g., if the compiler knows that the target doesn't support it.

@josephlr
Copy link
Contributor Author

@gnzlbg I removed the unstable feature, and commented on the appropriate thread_local tracking issue.

@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 15, 2019

Thanks!

@bors: r+

@bors
Copy link
Contributor

bors commented Jul 15, 2019

📌 Commit df34d17 has been approved by gnzlbg

@bors
Copy link
Contributor

bors commented Jul 15, 2019

⌛ Testing commit df34d17 with merge 47535e6...

bors added a commit that referenced this pull request Jul 15, 2019
Add __errno_location on Redox, DragonFlyBSD, Haiku

Currently [`libstd`](https://github.com/rust-lang/rust/blob/909f5a049415a815b23502a5498de9a99bbf276b/src/libstd/sys/unix/os.rs#L29-L49) and the [`getrandom` crate](https://github.com/rust-random/getrandom/pull/54/files#diff-027a56068e2bf3d31dc4273ee6e07034R12) have to use external declarations in order to implement `errno_location` across all UNIX platforms. This change adds bindings for the remaining UNIX platforms, allowing everyone to just use normal `libc` bindings.

This also removes the need for a seperate [`errno-dragonfly`](https://crates.io/crates/errno-dragonfly) crate.

Links to the relevant header files:

- Redox: [`relibc`'s `bits/errno.h`](https://github.com/redox-os/relibc/blob/master/include/bits/errno.h) uses `__errno_location`
- Haiku: [`posix/errno.h`](https://github.com/luciang/haiku/blob/master/headers/posix/errno.h) uses `_errnop`
- DragonFlyBSD: [`sys/errno.h`](https://github.com/DragonFlyBSD/DragonFlyBSD/blob/master/sys/sys/errno.h) uses `__error` just like FreeBSD (which makes sense)
  - Note that the `__error` function is inlined. I don't think this causes a problem.
@bors
Copy link
Contributor

bors commented Jul 15, 2019

☀️ Test successful - checks-cirrus-freebsd-11, checks-cirrus-freebsd-12, checks-travis, status-appveyor
Approved by: gnzlbg
Pushing 47535e6 to master...

@bors bors merged commit df34d17 into rust-lang:master Jul 15, 2019
@gnzlbg
Copy link
Contributor

gnzlbg commented Jul 15, 2019

libc 0.2.60 has been published with this - I'll update libc on rust-lang/rust

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants