Skip to content

How to reliably detect reentrancy #65

Closed
@pitdicker

Description

@pitdicker

Your RFC states "It is an error to reentrantly initialize the cell from f. Doing so results in a panic." Currently sync:OnceCell does not give that guarantee. I tried to see how a solution would look like, but haven't found something easy yet.

Option 1 was to use a ReentrantMutex, and an atomic. Suppose the atomic says an initializer is running. If we are able to lock the mutex, this must be a case of reentrant initialization. Otherwise the mutex will block, which is what we want in case another thread is busy initializing. See my not working experiment in https://github.com/pitdicker/once_cell/commit/bd4a940c94b41ee2b6f595854ea2565e0a76a73e. parking_lot does not expose a const {Raw}ReentrantMutex::new.

Option 2 is using some sort of thread id, which is stored in the OnceCell when the initializer starts to run. When another initializer sees the OnceCell is in the process of being initialized, it can compare the stored thread id to its own, and choose between blocking or panicking. Interestingly parking_lot::ReentrantMutex also needs some sort of thread id to function. I don't yet have working code though.

The disadvantage of both options is it would add quite some complexity, and 4 or 8 bytes to the size of the OnceCell. Is that worth the trouble?

Also getting a thread id is not ideal: std::process::id is not supported on all platforms (like CloudABI). And std::thread::Thread::id is an opaque type, so it can't (officially) be stored in an atomic, but needs a Cell and manual synchronisation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions