rust/library/std/src/sync
Petros Angelatos f0d487dce5 sync::mpsc: synchronize receiver disconnect with initialization
Receiver disconnection relies on the incorrect assumption that
`head.index != tail.index` implies that the channel is initialized (i.e
`head.block` and `tail.block` point to allocated blocks). However, it
can happen that `head.index != tail.index` and `head.block == null` at
the same time which leads to a segfault when a channel is dropped in
that state.

This can happen because initialization is performed in two steps. First,
the tail block is allocated and the `tail.block` is set. If that is
successful `head.block` is set to the same pointer. Importantly,
initialization is skipped if `tail.block` is not null.

Therefore we can have the following situation:

1. Thread A starts to send the first value of the channel, observes that
   `tail.block` is null and begins initialization. It sets `tail.block`
   to point to a newly allocated block and then gets preempted.
   `head.block` is still null at this point.
2. Thread B starts to send the second value of the channel, observes
   that `tail.block` *is not* null and proceeds with writing its value
   in the allocated tail block and sets `tail.index` to 1.
3. Thread B drops the receiver of the channel which observes that
   `head.index != tail.index` (0 and 1 respectively), therefore there
   must be messages to drop. It starts traversing the linked list from
   `head.block` which is still a null pointer, leading to a segfault.

This PR fixes this problem by waiting for initialization to complete
when `head.index != tail.index` and the `head.block` is still null. A
similar check exists in `start_recv` for similar reasons.

Fixes #110001

Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
2023-04-08 19:57:22 +02:00
..
barrier std: move "mod tests/benches" to separate files 2020-08-31 02:56:59 +00:00
condvar Remove condvar::two_mutexes test. 2022-05-05 21:47:13 +02:00
lazy_lock More inference-friendly API for lazy 2022-10-29 09:56:20 +01:00
mpmc sync::mpsc: synchronize receiver disconnect with initialization 2023-04-08 19:57:22 +02:00
mpsc std: add regression test for #107466 2023-02-17 15:58:15 +01:00
mutex std test: better type name, clarifying comment 2023-01-09 16:08:26 +01:00
once Stabilize poison API of Once, rename poisoned() 2021-02-04 15:20:14 +01:00
once_lock Move/rename lazy::Sync{OnceCell,Lazy} to sync::{Once,Lazy}Lock 2022-06-16 19:54:42 +04:00
remutex std: move ReentrantMutex to sync 2022-11-14 14:25:44 +01:00
rwlock Update rand in the stdlib tests, and remove the getrandom feature from it 2023-01-04 14:52:41 -08:00
barrier.rs Rollup merge of #87440 - twetzel59:fix-barrier-no-op, r=yaahc 2021-10-21 14:11:02 +09:00
condvar.rs std: remove lock wrappers in sys_common 2022-11-06 15:32:59 +01:00
lazy_lock.rs Stabilize a portion of 'once_cell' 2023-03-29 18:04:44 -04:00
mod.rs Documentation updates to better share the purpose of OnceCell/OnceLock 2023-03-29 18:04:44 -04:00
mutex.rs Apply suggestions from code review 2023-03-20 12:15:17 +01:00
once_lock.rs Stabilize a portion of 'once_cell' 2023-03-29 18:04:44 -04:00
once.rs std: optimize LazyLock size 2023-01-26 16:16:03 +01:00
poison.rs Auto merge of #97791 - m-ou-se:const-locks, r=m-ou-se 2022-06-19 08:20:36 +00:00
remutex.rs unequal → not equal 2023-03-15 23:55:48 +05:30
rwlock.rs std: remove lock wrappers in sys_common 2022-11-06 15:32:59 +01:00