Skip to content

unsafe: ScopedKey allows for Sync-ification of non-Sync data #25894

Closed
@Manishearth

Description

@Manishearth

There is an unsafe impl<T> Sync for KeyInner<T> { } in the scoped TLS module, which allows for sharing of data that wasn't meant to be shared.

An unqualified unsafe impl<T> Sync for Foo { } should only be used when Foo provides some sort of threadsafe locking mechanism. KeyInner and ScopedKey do not.

This lets us, for example, clone an Rc or RefCell between threads, in safe code:

scoped_thread_local!(static RC: Rc<u8>);
fn main() {
 RC.set(&Rc::new(1), ||{
     let y = &RC;
     let guard = scoped(|| {
        println!("Started 1");
        y.with(|slot|{
            for i in 1..10 {
                println!("Cloned in 1");
                slot.clone();
                sleep_ms(10);
            }
        });
        println!("Ended 1");
     });
     println!("Started 0");
     y.with(|slot| {
            for i in 1..10 {
                println!("Cloned in 0");
                slot.clone();
                sleep_ms(10);
            }
     });
     println!("Ended 0");
     guard.join();
 });
}

playpen

Here, we have Rc clones from different threads being interleaved, which can cause unsafety if there's a race on the refcount. We could also cause unsafety with a RefCell, or any other non-Sync type. ScopedKey basically lets us share &T across threads even if T: !Sync. I put the sleeps in there because somehow without them the routines are run serially.

Note that this is not a problem with the scoped() API. I'm using scoped() here because to exploit &T: Send, T:!Sync one needs to be able to share across threads, and Arc has an additional Send bound which ScopedKey doesn't satisfy. Any usable scoped API will probably have to make the assumption that &T: Send iff T:Sync. Nor is this a problem with Rc, since it can be done with RefCell, too.

Solution: Make it unsafe impl<T: Sync> Sync for KeyInner<T> { }

... I think. I'm not familiar with this API, and I'm not sure why it's even Sync in the first place.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P-mediumMedium priorityT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions