You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If we are to make this crate independent of rand_core, then we need to include an error type here.
We could simply copy the one rand_core uses; I think something simpler and equivalent on no_std may be preferable however. A quick look at the code shows that where we do include a cause, we are mostly just using an integer error code. Whether it is even worth forwarding the cause is another question.
I just reviewed the error handling — mostly I like it.
Would it be sensible to use common high-part for the two error constants?
It would be nice to have some ErrorKind enum (generated on-request from the error code, including common system-specific codes), but that can be added later.
Looking at Rand's ErrorKind, two get special handling:
Transient causes retry soon-ish; possibly we should trap io::ErrorKind::Interrupted and retry a few times?
NotReady allows detection of blocking, which isn't relevant to the current code here (I don't see much need to add this option, but we still could add it later if necessary, perhaps via fn is_ready()).
We follow Intel recommendations here (see section 5.2.1), IIRC in tight loop approximately each 2nd-4th execution of rdrand returns an "error", so I think it's different from Interrupted error.
I think retry-on-interrupt is applicable to all users as with RDRAND? The difference is importance; it may be that interrupt errors are rare enough that no one would notice?
keep getrandom as thin as possible.
I still plan to discuss using RDRAND as a backup option. That's another discussion, but if we did do so would have some impact here.
Using NonZeroU32 in the Error type implies a requirement on rustc ≥ 1.28. Once we port Rand to use this, that requirement would be implied there too. Do we want this?
Alternatively we could just use u32; would we lose much? Likely Result<(), Error> would be larger due to the missed non-zero optimisation. Is this worth it? (In the longer term, possibly so?)
The WASM implementations in #10 left a few errors poorly handled (marked TODO): two cases with a static string description and two cases with a stdweb::web::error::Error type (which is apparently a reference to a JS value).
Being able to forward an error would be nice but is not essential. Safely forwarding another error requires either a tagged enum over all possible sources or an allocator, as I understand it; neither are ideal.
So what is the best option? Can a single type be sufficient for both std and no_std uses?
And can we design a better solution for rand_core and use the same type there? Should we just use the existing rand_core type here?
Perhaps the best option is to keep the current type but map each error classification to a specific constant.
How do you think we should deal with forwarded errors then?
use stdweb::web::error::Error as WebError;
let err: WebError = js!{ return @{ result }.error }.try_into().unwrap();
Err(UNAVAILABLE_ERROR) // TODO: forward err
The only useful methods this type gives us come from the Debug, Display and std::error::Error implementations. I don't want to start matching against display strings, so then we can't do anything useful here.
There is an option we could use here if we wanted: something akin to the UNIX errno, but using an AtomicPtr to store a &'static str, behind an API like
fnset_err(msg:&'staticstr);fnget_last_err() -> &str;// or, for cfg(std):fnset_err<T:ToString>(msg:T);
This would be fully no_std compatible with minimal run-time overhead (on successful usage). There are two drawbacks:
some extra code size / memory usage
a more complex API, which may be a problem for inclusion in std; also we would essentially be piggy-backing this crate to define an Error type possibly used elsewhere in Rand
I don't think that such extra-complexity is warranted (plus it will be even less idiomatic that NonZeroU32). On panics users by default already will get an error message specifying that it originated in getrandom. After that they'll have to look into platform specific details either way.
As was written in the rust-random/rand#715 I think in addition to msg we could add is_retryable method and RETRYABLE error constant. Also I am not sure if automatically retrying on Interrupted error is a correct behavior. For example on Linux interrupt handler could use SA_RESTART flag to continue interruptible operations without EINTR, so hard-coding retry loop may be a wrong approach.
Activity
newpavlov commentedon Jan 19, 2019
I would prefer to use a simple (non-exhaustive) error enum without any associated explicit error codes.
dhardy commentedon Jan 20, 2019
If we can translate the source error codes appropriately, that's probably the best option.
dhardy commentedon Feb 18, 2019
I just reviewed the error handling — mostly I like it.
Would it be sensible to use common high-part for the two error constants?
It would be nice to have some
ErrorKindenum (generated on-request from the error code, including common system-specific codes), but that can be added later.Looking at Rand's
ErrorKind, two get special handling:Transientcauses retry soon-ish; possibly we should trapio::ErrorKind::Interruptedand retry a few times?NotReadyallows detection of blocking, which isn't relevant to the current code here (I don't see much need to add this option, but we still could add it later if necessary, perhaps viafn is_ready()).newpavlov commentedon Feb 18, 2019
Hm, I think we better to do it in the
rand_oswrapper instead and keepgetrandomas thin as possible.I think conversion into
io::Errormostly covers the need for an additionalErrorKind.dhardy commentedon Feb 18, 2019
We already do repeat-on-error for RDRAND.
Excepting that we have a couple of custom error codes.
newpavlov commentedon Feb 18, 2019
We follow Intel recommendations here (see section 5.2.1), IIRC in tight loop approximately each 2nd-4th execution of
rdrandreturns an "error", so I think it's different fromInterruptederror.dhardy commentedon Feb 18, 2019
I think retry-on-interrupt is applicable to all users as with RDRAND? The difference is importance; it may be that interrupt errors are rare enough that no one would notice?
I still plan to discuss using RDRAND as a backup option. That's another discussion, but if we did do so would have some impact here.
dhardy commentedon Feb 22, 2019
Using
NonZeroU32in theErrortype implies a requirement on rustc ≥ 1.28. Once we port Rand to use this, that requirement would be implied there too. Do we want this?Alternatively we could just use
u32; would we lose much? LikelyResult<(), Error>would be larger due to the missed non-zero optimisation. Is this worth it? (In the longer term, possibly so?)dhardy commentedon Feb 26, 2019
The WASM implementations in #10 left a few errors poorly handled (marked TODO): two cases with a static string description and two cases with a
stdweb::web::error::Errortype (which is apparently a reference to a JS value).Being able to forward an error would be nice but is not essential. Safely forwarding another error requires either a tagged enum over all possible sources or an allocator, as I understand it; neither are ideal.
So what is the best option? Can a single type be sufficient for both
stdandno_stduses?And can we design a better solution for
rand_coreand use the same type there? Should we just use the existingrand_coretype here?Perhaps the best option is to keep the current type but map each error classification to a specific constant.
newpavlov commentedon Feb 26, 2019
I prefer this option. I think we can document error codes in the
getrandomdocumentation and then map those codes torand_core::Errorinrand_os.dhardy commentedon Feb 26, 2019
How do you think we should deal with forwarded errors then?
The only useful methods this type gives us come from the
Debug,Displayandstd::error::Errorimplementations. I don't want to start matching against display strings, so then we can't do anything useful here.Should we use
logto print a warning?newpavlov commentedon Mar 4, 2019
Yes, I think it will be the best option.
dhardy commentedon Mar 7, 2019
There is an option we could use here if we wanted: something akin to the UNIX
errno, but using anAtomicPtrto store a&'static str, behind an API likeThis would be fully
no_stdcompatible with minimal run-time overhead (on successful usage). There are two drawbacks:std; also we would essentially be piggy-backing this crate to define anErrortype possibly used elsewhere in Randnewpavlov commentedon Mar 11, 2019
I don't think that such extra-complexity is warranted (plus it will be even less idiomatic that
NonZeroU32). On panics users by default already will get an error message specifying that it originated ingetrandom. After that they'll have to look into platform specific details either way.As was written in the rust-random/rand#715 I think in addition to
msgwe could addis_retryablemethod andRETRYABLEerror constant. Also I am not sure if automatically retrying onInterruptederror is a correct behavior. For example on Linux interrupt handler could useSA_RESTARTflag to continue interruptible operations withoutEINTR, so hard-coding retry loop may be a wrong approach.newpavlov commentedon May 30, 2019
I think we can close this issue?