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
{{ message }}
Repository navigation
Wrong optimization of Some(Rc<RefCell<...>>) in thread_local! (STATUS_ILLEGAL_INSTRUCTION) #58684
It seems that there is a some sort of wrong optimization of Some(Rc<RefCell<...>>) by using thread_local!. Code like this one https://github.com/michaelvoronov/rust_poc_1 is failed on
changed the title [-]Wrong optimization of Some(Rc<RefCell<...>>) in thread_local![/-][+]Wrong optimization of Some(Rc<RefCell<...>>) in thread_local! (STATUS_ILLEGAL_INSTRUCTION)[/+]on Feb 23, 2019
triage: P-high. Leaving nomination label. Seems like candidate for both 1. narrowing test case and 2. attempting bisection (assuming one can backtrack to an earlier stable rustc that didn't have the fault, e.g. maybe prior to last LLVM upgrade).
I spent some time narrowing this down to a smaller test case.
I did the narrowing by first cut-and-pasting the arraydeque code as a submodule of the crate, and then trimming as much as I could out of that arraydeque submodule.
But now that I have something plausible, I'm worried that I may have narrowed it too much. (That, or exposed some fundamental unsoundness in the original code.)
For reference, the code I now have is this (play):
Hmm. Based on stepping through the execution of local::LocalKey::with (→ try_with → init), I wonder if somehow the use of mem::uninitialized is creating a value that looks like the tag that is used to represent Option::None in the thread local's instance of GM, and thus its tickling this code here:
Yeah at this point I'm assuming that unintialized is filling in the Rc::ptr field (which is NonNull) with a null, and that then is treated as an Option::None in the thread/local.rs code I quoted earlier.
My question now is: Which component in the original composition of crates is at fault here?
My question now is: Which component in the original composition of crates is at fault here?
My immediate reaction (as conditioned by @RalfJung) is to say mem::uninitialized is at fault, and miri agrees (I'm aware this is a kind of circular reasoning).
Activity
[-]Wrong optimization of Some(Rc<RefCell<...>>) in thread_local![/-][+]Wrong optimization of Some(Rc<RefCell<...>>) in thread_local! (STATUS_ILLEGAL_INSTRUCTION)[/+]jonas-schievink commentedon Feb 23, 2019
Reproduces on Linux (both on stable 1.32.0 and 1.34.0-nightly (146aa60 2019-02-18)).
Would be nice to get rid of the arraydeque dependency.
Mark-Simulacrum commentedon Feb 23, 2019
Cc @rust-lang/compiler
michaelwoerister commentedon Feb 25, 2019
Nominating for priority assignment.
pnkfelix commentedon Feb 28, 2019
triage: P-high. Leaving nomination label. Seems like candidate for both 1. narrowing test case and 2. attempting bisection (assuming one can backtrack to an earlier stable rustc that didn't have the fault, e.g. maybe prior to last LLVM upgrade).
pnkfelix commentedon Feb 28, 2019
assigning to self for initial investigation and removing nomination label.
pnkfelix commentedon Mar 5, 2019
I spent some time narrowing this down to a smaller test case.
I did the narrowing by first cut-and-pasting the
arraydequecode as a submodule of the crate, and then trimming as much as I could out of thatarraydequesubmodule.But now that I have something plausible, I'm worried that I may have narrowed it too much. (That, or exposed some fundamental unsoundness in the original code.)
For reference, the code I now have is this (play):
pnkfelix commentedon Mar 5, 2019
Hmm. Based on stepping through the execution of
local::LocalKey::with(→try_with→init), I wonder if somehow the use ofmem::uninitializedis creating a value that looks like the tag that is used to representOption::Nonein the thread local's instance ofGM, and thus its tickling this code here:rust/src/libstd/thread/local.rs
Lines 264 to 274 in f22dca0
oli-obk commentedon Mar 5, 2019
Here's a smaller, self-contained example not using thread locals: https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=09537cc61a99276e4bace501fd9eb59f. I can't test it against miri, because miri immediately bails out on the
mem::uninitialized()pnkfelix commentedon Mar 5, 2019
Yeah at this point I'm assuming that
unintializedis filling in theRc::ptrfield (which isNonNull) with anull, and that then is treated as anOption::Nonein thethread/local.rscode I quoted earlier.My question now is: Which component in the original composition of crates is at fault here?
oli-obk commentedon Mar 5, 2019
When changing it to support miri (by using a union instead of
mem::uninitialized), it works again: https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=ccc12441024623d4895720b4a11f5c9bMy immediate reaction (as conditioned by @RalfJung) is to say
mem::uninitializedis at fault, and miri agrees (I'm aware this is a kind of circular reasoning).nagisa commentedon Mar 5, 2019
ManuallyDropis notMaybeUninitand therefore must be initialized with valid data. See #58780.pnkfelix commentedon Mar 5, 2019
@oli-obk has convinced me that this is not a problem in our std library; it arises because the
arraydequeis misusingmem::uninitialized.(I have filed a bug against arraydeque here: andylokandy/arraydeque#12)