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
Rust JSG: jsg::Rc moved out of a traced field is neither strong nor traced #7976
A jsg::Rc that GC has visited inside a traced field gives up its
strong reference and relies on its parent's trace instead (its strong flag is false). If Rust then moves it out of the field, for
example with Cell::take, it is neither strong nor traced. A GC can
then collect the resource's JS wrapper while Rust still holds the Rc.
This is not a use-after-free: the Rc still keeps the Rust value and
the C++ Wrappable allocated. But the resource loses its JS identity
(a new wrapper is created the next time it is passed to JavaScript),
and nothing traces the resource's own fields any more, so a TracedGlobal it holds can lose its value and as_local panics.
#[jsg_resource]implScheduler{#[jsg_method]fnrun(&self,lock:&mut jsg::Lock){let task = self.pending.take().unwrap();// moved out, not strongcall_into_js(lock);// a GC here can collect task's wrapper
task.callback(lock);}}
C++ JSG doesn't have this problem: the jsg::Ref move constructor
makes a moved-from traced reference strong again
(src/workerd/jsg/jsg.h, Ref(Ref&& other) calls addStrongRef()
when other.strong is false). Rust has no hook on moves, which is the
same reason a weak TracedGlobal needed a stable boxed slot.
Workaround: clone the Rc after moving it out
(self.pending.take().unwrap().clone()); a clone always starts
strong.
Possible fixes: a jsg-provided field type whose take/replace
returns a strong Rc, or making traced fields hold a type that can't
be moved out without going through such an API. Reported by @littledivy in review of #7966.
Activity
Document the Rust JSG safety rules
Document the Rust JSG safety rules
Document the Rust JSG safety rules
Document the Rust JSG safety rules
Write down and check the Rust JSG safety rules (#7965)
Add jsg::Cell and jsg::RefCell for traced fields
Reject a jsg::Rc or TracedGlobal in a std Cell or RefCell field