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

sync::mpsc: synchronize receiver disconnect with initialization #110089

Merged
merged 1 commit into from
Apr 13, 2023

Commits on Apr 8, 2023

  1. 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 rust-lang#110001
    
    Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
    petrosagg committed Apr 8, 2023
    Configuration menu
    Copy the full SHA
    f0d487d View commit details
    Browse the repository at this point in the history