Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unix: RwLock is incorrect #53127

Open
RalfJung opened this Issue Aug 6, 2018 · 8 comments

Comments

Projects
None yet
4 participants
@RalfJung
Copy link
Member

RalfJung commented Aug 6, 2018

I think the sys::unix::rwlock implementation is incorrect in the sense that it has undefined behavior, for two reasons:

  • The access to write_locked is not properly synchronized: In read, we access write_locked even if pthread_rwlock_rdlock failed. This is fixed.
  • Worse, POSiX read-write locks have UB when the thread holding the write lock attempts to acquire it again -- and yet nothing is stopping exactly that from happening in write. If we really want to use POSIX rwlocks, I think we have to implement a reentrancy detector. (And then maybe we also want to use that for mutex, so that we can use the static initializer and the most efficient code path?)
@RalfJung

This comment has been minimized.

Copy link
Member Author

RalfJung commented Aug 6, 2018

I based my statements on http://pubs.opengroup.org/onlinepubs/7908799/xsh/pthread_rwlock_wrlock.html. @sfackler points out that at https://linux.die.net/man/3/pthread_rwlock_wrlock, behavior for re-acquiring the write lock is defined as "may deadlock" -- but not UB. However, we also use this implementation on non-Linux platforms, e.g. macOS.

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Aug 6, 2018

macOS does explicitly identify the behavior as undefined.

@RalfJung

This comment has been minimized.

Copy link
Member Author

RalfJung commented Aug 29, 2018

FWIW, RwLock is also UB on Windows -- actually, even Mutex is wrong there.

I think we should stop using the platform-specific implementations, and just roll our own based on thread (un)parking.

@sfackler

This comment has been minimized.

Copy link
Member

sfackler commented Aug 29, 2018

cc @alexcrichton - we talked about this a bit during RustConf.

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Aug 29, 2018

I agree that we're basically at the point that there's a ridiculous amount of constraints from OS primitives that the only program which doesn't have undefined behavior is correct ones, and we all know how often we write correct programs.

All these discussions are spread out over a number of issues though and PRs, and it's really difficult to keep it all in my own head at least. "This is UB" is a very strong motivation for reimplementing the standard library's primitives, but I think the scale of a change such as this would probably want to go through the RFC process. Such an RFC would be a great location to centralize all the various hazards of OS primitives and how unreasonable it is for us to try to appease all possible implementations. That in turns provides excellent motivation for alternative strategies.

@retep998

This comment has been minimized.

Copy link
Member

retep998 commented Aug 29, 2018

You mean like this RFC? rust-lang/rfcs#1632

@RalfJung

This comment has been minimized.

Copy link
Member Author

RalfJung commented Aug 29, 2018

Correction: Even some correct programs are UB. Reentrancy on the read lock of an RwLock is a perfectly reasonable thing to do, and yet Windows declares it UB.

Whether reentrancy that leads to deadlocks is "correct" is open for interpretation, I guess ;) but anyway, it is safe, and hence "correct enough" for UB to be critical.

@alexcrichton

This comment has been minimized.

Copy link
Member

alexcrichton commented Sep 20, 2018

I've opened an internals post to continue more long-form discussion on the topic of continuing to fix these issues.

bors added a commit that referenced this issue Apr 3, 2019

Auto merge of #56410 - faern:add-parking-lot, r=<try>
Use the parking_lot locking primitives

This PR adds the [`parking_lot`](https://crates.io/crates/parking_lot) code to libstd and uses it for the `sys_common::{mutex,rwlock,condvar,remutex}` implementations.

This has been discussed in https://internals.rust-lang.org/t/standard-library-synchronization-primitives-and-undefined-behavior/8439/9

Thanks @Amanieu for mentoring when doing this, and basically all the code is his as well of course.

Fixes #35836
Fixes #53127
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.