errno v0.1.0

Source
Reading C's thread-local errno, and which C runtime it lives in.

CRuntime

// Windows
pub const CRuntime = "ucrtbase.dll";

// Linux
pub const CRuntime = "libc.so.6";

// macOS
pub const CRuntime = "libSystem.B.dylib";

// FreeBSD
pub const CRuntime = "libc.so.7";

The shared object this target's C runtime lives in.

Source

StreamRuntime

// Windows
pub const StreamRuntime = "msvcrt.dll";

// Linux
pub const StreamRuntime = "libc.so.6";

// macOS
pub const StreamRuntime = "libSystem.B.dylib";

// FreeBSD
pub const StreamRuntime = "libc.so.7";

The shared object C::StdIo and C::Time are bound to, which on Windows is a different one. The Universal CRT does not export the formatted-output family, so those two modules bind the legacy runtime. It keeps its own errno, its own stream table and its own locale, so a failure reported by a call through either module is readable only through ErrnoFor(CRuntimeArea::Streams).

OverloadSummary
pub const StreamRuntime = "msvcrt.dll";The shared object C::StdIo and C::Time are bound to, which on Windows is a different one.
pub const StreamRuntime = "libc.so.6";The shared object C::StdIo and C::Time are bound to, which on this target is the same one.
pub const StreamRuntime = "libSystem.B.dylib";The shared object C::StdIo and C::Time are bound to, which on this target is the same one.
pub const StreamRuntime = "libc.so.7";The shared object C::StdIo and C::Time are bound to, which on this target is the same one.

Source

CRuntimeArea

pub enum CRuntimeArea: uint8 {
    General = 0,
    Streams = 1
}

Which of the package's C runtimes a call belongs to. On Windows this package spans two: StdLib and Math bind the Universal CRT, while StdIo and Time bind the legacy runtime, because the Universal CRT does not export the formatted-output family. The two keep separate errno storage, so reading one after a call into the other reports a value belonging to something else entirely. Everywhere else there is one runtime and both cases name it, so a caller that always passes the area matching the module it called is right on all four systems and needs no target branch of its own.

Source

Cases

NameValueDescription
General0Where C::StdLib and C::Math are bound, and what plain Errno reads.
Streams1Where C::StdIo and C::Time are bound. The same runtime as General except on Windows.

SeparateStreamRuntime

pub const SeparateStreamRuntime: bool = #target.os == OperatingSystem::Windows;

Whether the two areas are really two runtimes on this target. True on Windows and false everywhere else. A caller that passes the right area never needs to read this; it is here so that a program can say why it is being careful, and so that a test can assert the split exists where it is supposed to and does not where it is not.

Source

ErrnoLocationFor

pub func ErrnoLocationFor(area: CRuntimeArea) -> *var c_int

The address of the calling thread's errno, in the runtime area names. Returns a pointer that runtime owns, valid for as long as the calling thread runs. Writing through it is how C's errno = 0 is spelled, which a caller does before a call whose failure is only reported through errno. Pass the area matching the module whose call is being checked: Streams after anything from C::StdIo or C::Time, General after anything from C::StdLib or C::Math. Passing the wrong one is not a compile error and not a crash; it reads a different thread-local integer, which is the whole hazard this exists to remove. Cannot fail. Runs in constant time and allocates nothing. The address belongs to the calling thread and must not be handed to another one.

Source

Parameters

NameTypeDescription
areaCRuntimeAreawhich runtime's storage to reach

Returns: the address of that runtime's errno for this thread

ErrnoFor

pub func ErrnoFor(area: CRuntimeArea) -> c_int

The calling thread's current errno value, in the runtime area names. Meaningful only after a call that documents setting it: no C function clears errno on success, so a value left over from an earlier failure is still there. Clear it through ErrnoLocationFor before the call whose failure is to be read. Cannot fail. Runs in constant time and allocates nothing.

Source

Parameters

NameTypeDescription
areaCRuntimeAreawhich runtime's storage to read

Returns: that runtime's errno for this thread

ErrnoLocation

pub func ErrnoLocation() -> *var c_int

The address of the calling thread's errno, in the runtime C::StdLib and C::Math are bound to. Exactly ErrnoLocationFor(CRuntimeArea::General), and the spelling to use when the call being checked came from one of those two modules. After a call from C::StdIo or C::Time on Windows this reads the wrong runtime's storage, which is what ErrnoLocationFor exists to let a caller avoid. Writing through it is how C's errno = 0 is spelled, which a caller does before a call whose failure is only reported through errno. Cannot fail. Runs in constant time and allocates nothing. The address belongs to the calling thread and must not be handed to another one.

Source

Returns: the address of the general runtime's errno for this thread

Errno

pub func Errno() -> c_int

The calling thread's current errno value. Takes nothing and returns the value by copy. Meaningful only after a call that documents setting it: no C function clears errno on success, so a value left over from an earlier failure is still there. Clear it with *ErrnoLocation() = 0 before the call whose failure is to be read. On Windows this reads the Universal CRT's errno, which is the one C::StdLib and C::Math set. C::StdIo and C::Time are still bound to the legacy msvcrt.dll, whose errno is a different variable in a different runtime, so a failure reported by a call in either of those modules is not visible here. That split is a known defect: the Universal CRT does not export the formatted-output family, so moving those modules across needs the __stdio_common_* entry points declared first. Cannot fail. Runs in constant time and allocates nothing.

Source

Returns: the general runtime's errno for this thread

EDOM

pub const EDOM: c_int = 33;

EDOM: an argument outside the domain over which a math function is defined.

Source

ERANGE

pub const ERANGE: c_int = 34;

ERANGE: a result too large or too small for the return type to express.

Source

EILSEQ

// Windows
pub const EILSEQ: c_int = 42;

// Linux
pub const EILSEQ: c_int = 84;

// macOS
pub const EILSEQ: c_int = 92;

// FreeBSD
pub const EILSEQ: c_int = 86;

EILSEQ: a byte sequence that does not form a valid character.

Source