Skip to content

Turn errno into an enum #4233

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

Closed
wants to merge 3 commits into from
Closed

Conversation

daurnimator
Copy link
Contributor

Currently compiler is dieing with a segfault when I test locally.

@daurnimator daurnimator added the standard library This issue involves writing Zig code for the standard library. label Jan 19, 2020
@@ -817,8 +817,8 @@ pub const Loop = struct {
@atomicStore(i32, &self.os_data.fs_queue_item, 1, AtomicOrder.SeqCst);
const rc = os.linux.futex_wake(&self.os_data.fs_queue_item, os.linux.FUTEX_WAKE, 1);
switch (os.linux.getErrno(rc)) {
0 => {},
os.EINVAL => unreachable,
@intToEnum(os.linux.Errno, 0) => {},
Copy link
Member

Choose a reason for hiding this comment

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

it seems clear to me that there should be a tag value of Errno which represents "no error" and has value 0.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought that.... and then thought that getErrno returning an optional would work better: what do you think of that?

Copy link
Member

Choose a reason for hiding this comment

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

I don't think that's the correct data layout. These ABIs have 0 as an in-bound value.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lacking that for now, #3806 could put 0 out of range, and hence make it so 0 is null

@LemonBoy
Copy link
Contributor

The problem: extern enum(u12) is rejected by the compiler, u12 enums are not ABI-compatible with C, the compiler knows that and successfully rejects it.
The solution: extern enum(c_int) (or u32 ? or i32 ?)
The problem (pt. 2): The compiler detects the problem but we're missing some error-handling code somewhere and so it doesn't bubble up to the user nor it halts the compilation.

LemonBoy added a commit to LemonBoy/zig that referenced this pull request Jan 19, 2020
@daurnimator
Copy link
Contributor Author

@LemonBoy we need an extern enum because we want to have a duplicate value (e.g. alias EWOULDBLOCK to EAGAIN)

@LemonBoy
Copy link
Contributor

we need an extern enum because we want to have a duplicate value

Nobody said you cannot use an extern enum, you just have to use a correct type for the tag

@daurnimator
Copy link
Contributor Author

But we do want @enumToInt to produce a u12...

@LemonBoy
Copy link
Contributor

We always want things we can't have... I think that matching the libcs by using a c_int is your best choice if you really want to use a enum here.

andrewrk pushed a commit that referenced this pull request Jan 19, 2020
@daurnimator
Copy link
Contributor Author

@andrewrk what do you think?

  • we could make it so duplicate values are allowed in normal enums?
  • we could permit non-C-ABI sizes (e.g. u12) in extern enums (potentially useful if some external library has a bitfield that should be modeled as an enum)

@daurnimator daurnimator force-pushed the errno-enum branch 4 times, most recently from 5ab97ba to 20657a1 Compare January 20, 2020 03:07
@LemonBoy
Copy link
Contributor

Is there some tangible benefit from having the errno tag u12 instead of a more standard c_int?
Since it's now a non-exhaustive enum we get type-safety with no soundness problems related to the kernel adding new values I think there are no added benefits from using such a narrow type (the good thing is that less casts are needed, you can even type the extern errno definition with such a enum if c_int is used as tag type.
Moreover, while it's quite unlikely that errno will get more than 4095 entries, the upper boundary is just a side-effect of how the syscalls have been implemented in Linux and how the error condition is signaled.

@daurnimator
Copy link
Contributor Author

Is there some tangible benefit from having the errno tag u12 instead of a more standard c_int?

Has already saved me a few times:

  • Trying to jam a usize into an errno without casting to u12 on linux should be an error
  • Trying to jam a signed integer into an errno without bitcasting to unsigned should be an error

@LemonBoy
Copy link
Contributor

LemonBoy commented Jan 20, 2020

Trying to jam a usize into an errno without casting to u12 on linux should be an error

You need a @intToEnum so it'd be a compiler error anyway.

Trying to jam a signed integer into an errno without bitcasting to unsigned should be an error

Then use an unsigned tag type.

@daurnimator
Copy link
Contributor Author

You need a @intToEnum so it'd be a compiler error anyway.

I was. @intToEnum(Errno, myu12) should succeed while @intToEnum(Errno, someusize) should fail. The proper incantation was: @intToEnum(Errno, @intCast(u12, someusize)).

Then use an unsigned tag type.

Then we match neither linux ABI or libcs.

@LemonBoy
Copy link
Contributor

I was. @intToEnum(Errno, myu12) should succeed while @intToEnum(Errno, someusize) should fail.

Alright, that's a possible footgun.

Then we match neither linux ABI or libcs

The "linux ABI" for the syscall error codes states that they are >= 0 v <= 4095, I think that we can safely assume the signedness here ;)
libcs follow the Posix standard where errno is defined as int with no care about "trying to jam a signed integer into an errno without bitcasting to unsigned", everything is fair game in the C land.

@andrewrk
Copy link
Member

I'm not necessarily saying "no" to this, but this pull request is not mergeable as is and doesn't appear to be on the path to that anytime soon.

@andrewrk andrewrk closed this Feb 18, 2020
@andrewrk
Copy link
Member

we could make it so duplicate values are allowed in normal enums?
we could permit non-C-ABI sizes (e.g. u12) in extern enums (potentially useful if some external library has a bitfield that should be modeled as an enum)

I don't think either of these are desirable language changes. I don't like the idea of bending the language over backwards to accommodate errno.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
standard library This issue involves writing Zig code for the standard library.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants