Skip to content

segfault in stdexec::__shared::__shared_state for many split with gcc #1743

@romintomasetti

Description

@romintomasetti

Having more than one split does not work will gcc (using 71d22ca).

For the code snippet, see below dockerfile.

I tried with gcc 12, 13, and 14: it always compiles, and always segfaults (see below trace).

It's fine with clang 21.

Here is the output for g++-14

Program received signal SIGSEGV, Segmentation fault.
0x00005a14be8701fb in stdexec::__shared::__shared_state<stdexec::(anonymous namespace)::__sexpr<stdexec::{lambda()#7}{}>, stdexec::__env::env<> >::__inc_ref() ()
#0  0x00005a14be8701fb in stdexec::__shared::__shared_state<stdexec::(anonymous namespace)::__sexpr<stdexec::{lambda()#7}{}>, stdexec::__env::env<> >::__inc_ref() ()
#1  0x00005a14be86f8bd in _ZN7stdexec8__shared5__boxINS_12_GLOBAL__N_17__sexprIXtlNS_UlvE5_EEEEENS_5__env3envIJEEELb1EEC2ERKS9_QT1_ ()
#2  0x00005a14be86d88d in stdexec::__detail::__captures<stdexec::__split::__split_t, stdexec::__shared::__box<stdexec::(anonymous namespace)::__sexpr<stdexec::{lambda()#7}{}>, stdexec::__env::env<>, true> >(stdexec::__split::__split_t, stdexec::__shared::__box<stdexec::(anonymous namespace)::__sexpr<stdexec::{lambda()#7}{}>, stdexec::__env::env<>, true>&&)::{lambda<typename $T0, typename $T1>($T0, $T1&&)#1}::__captures({lambda<typename $T0, typename $T1>($T0, $T1&&)#1} const&) ()
#3  0x00005a14be86d8b3 in stdexec::(anonymous namespace)::__sexpr<stdexec::{lambda()#9}{}>::__sexpr(stdexec::(anonymous namespace)::__sexpr<stdexec::{lambda()#9}{}> const&) ()
#4  0x00005a14be86d8ec in auto stdexec::__then::then_t::operator()<stdexec::(anonymous namespace)::__sexpr<stdexec::{lambda()#9}{}>&, main::{lambda()#2}>(stdexec::(anonymous namespace)::__sexpr<stdexec::{lambda()#9}{}>&, main::{lambda()#2}) const ()
#5  0x00005a14be86f2b3 in main ()
A debugging session is active.

Use the dockerfile with the following command to see what's going on:

docker buildx build --tag=test --progress=plain - < dockerfile && docker run --rm -it test bash -c "gdb -ex run -ex bt -ex quit ./a.out"

ARG COMPILER=gcc

# Base requirements.
FROM ubuntu:24.04 AS base

RUN apt update
RUN apt --yes --no-install-recommends install git ca-certificates git wget lsb-release gpg software-properties-common gdb

RUN git clone --branch=main https://github.com/NVIDIA/stdexec
RUN cd stdexec && git checkout 71d22ca77d5a1eb2b107ed2c8db6cbea90f70c68

# Install GCC.
FROM base AS gcc

ARG GCC_VERSION=14
RUN apt --yes --no-install-recommends install g++-${GCC_VERSION}

# Install Clang.
FROM base AS clang

ARG CLANG_VERSION=21

RUN <<EOF
    set -ex

    wget https://apt.llvm.org/llvm.sh
    chmod +x llvm.sh
    ./llvm.sh ${CLANG_VERSION}
    rm llvm.sh

    apt --yes --no-install-recommends install clang-${CLANG_VERSION}
EOF

# Let's try out.
FROM ${COMPILER}

COPY <<EOF test_when_all.cpp
#include <iostream>

#include "stdexec/execution.hpp"

#define THEN_SHOW_ID ::stdexec::then([]() -> void { std::cout << std::this_thread::get_id() << std::endl; })

int main()
{
    ::stdexec::inline_scheduler scheduler{};

    auto fork_A = ::stdexec::schedule(scheduler)
        | THEN_SHOW_ID
        | ::stdexec::split();

    auto chain_A = ::stdexec::when_all(
                  fork_A  | THEN_SHOW_ID,
        std::move(fork_A) | THEN_SHOW_ID
    );

    auto fork_B = std::move(chain_A)
        | ::stdexec::continues_on(scheduler)
        | ::stdexec::split();

    auto chain_B = ::stdexec::when_all(
                  fork_B  | THEN_SHOW_ID,
        std::move(fork_B) | THEN_SHOW_ID
    );

    ::stdexec::sync_wait(std::move(chain_B));
}
EOF

RUN g++-14 --version
RUN g++-14 -Wall -Wextra -Werror -std=c++20 -I/stdexec/include test_when_all.cpp

CMD ./a.out

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions