c++asynchronousseastar

Segfault cased by fn arg using seastar library


In the code below, if I use local var called chunk, this program works as expected, but if I use same variable type but passed as a fn arg I'm getting segfault. I'm moving those objects so there shouldn't be a problem.

#include <seastar/core/app-template.hh>
#include <seastar/util/log.hh>
#include <seastar/core/coroutine.hh>
#include <seastar/core/sleep.hh>
#include <seastar/coroutine/maybe_yield.hh>
#include <seastar/coroutine/generator.hh>
#include <seastar/core/circular_buffer.hh>
#include <seastar/coroutine/all.hh>
#include <seastar/core/when_all.hh>
#include <seastar/core/reactor.hh>
#include <seastar/coroutine/parallel_for_each.hh>
#include <seastar/core/do_with.hh>

#include <stdexcept>
#include <vector>
#include <iostream>
#include <chrono>
#include <seastar/core/circular_buffer.hh>
#include <seastar/core/sleep.hh>
#include <seastar/coroutine/generator.hh>
#include <ranges>

seastar::coroutine::experimental::generator<char, seastar::circular_buffer>
generate_chars(coroutine::experimental::buffer_size_t, std::vector<char>&& buf) {
                std::ranges::sort(buf,ranges::greater());
    while (std::size(buf)) {
        char some_char = buf.back();
        buf.pop_back();
        co_yield some_char;
    }
}

future<> print_generated_chars(vector<char>&& chunk_)//instead of fn arg (which crashes) use local var chunk
{
    std::vector<char> chunk{'1','8','7','6','5','4','3','2'};//this will not cause segfault
    auto char_generator = generate_chars(coroutine::experimental::buffer_size_t{5},std::move(chunk));
    while (std::optional<char> c = co_await char_generator())
    {
        std::cout << "char: " << c.value() << '\n';
    }
}

int main(int argc, char** argv) {
    app_template app;

    return app.run(argc, argv, [&app] {
        
        std::vector<char> buf_1{'1','8','7','6','5','4','3','2'};
        return print_generated_chars(std::move(buf_1));
    });
}

Solution

  • I cannot post the code to the comment, so let me show it here.

    I never worked with the co-routines and I do not know how the object lifetime works on that side. Maybe there are nuances. If you say that the local vector works, try changing your code into the following way:

    future<> print_generated_chars(vector<char>&& chunk)
    {
        // Take an ownership over the `chunk`
        auto local_chunk = std::move(chunk);
    
        auto char_generator = generate_chars(
           coroutine::experimental::buffer_size_t{5},
           std::move(local_chunk));
    
        while (std::optional<char> c = co_await char_generator())
        {
            std::cout << "char: " << c.value() << '\n';
        }
    }