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

Abandoned generator leaks memory #2190

Open
xemul opened this issue Apr 15, 2024 · 1 comment
Open

Abandoned generator leaks memory #2190

xemul opened this issue Apr 15, 2024 · 1 comment
Assignees

Comments

@xemul
Copy link
Contributor

xemul commented Apr 15, 2024

Consider the following test case (can be applied to tests/unit/coroutines_test.cc)

#include <seastar/core/queue.hh>

coroutine::experimental::generator<int> my_generator() {
    auto q = make_shared<queue<std::optional<int>>>(16);
    auto f = q->push_eventually(1).then([] {
        return sleep(1s);
    }).then([q] {
        return q->push_eventually({});
    });

    while (auto i = co_await q->pop_eventually()) {
        co_yield *i;
    }

    co_await std::move(f);
}

SEASTAR_TEST_CASE(test_early_abort_generator)
{
    auto gen = my_generator();
    std::optional<int> i = co_await gen();
    fmt::print("{}\n", i.value_or(42));
}

What it does is creates a my_generator, then co-awaits a single result out of it, then exists and (implicitly) destroys the generator. Generator itself, in turn, wants to generate two values, not one. But being destroyed early it leaks memory, reported in debug mode

=================================================================
==6430==ERROR: LeakSanitizer: detected memory leaks

Indirect leak of 168 byte(s) in 1 object(s) allocated from:
    #0 0x582641 in operator new(unsigned long) (/home/xemul/src/seastar/build/debug/tests/unit/coroutines_test+0x582641) (BuildId: 7560442d38b7f9121245a32bf098080d3a5f56a1)
    #1 0x830a8c in seastar::shared_ptr<seastar::queue<std::optional<int>>> seastar::shared_ptr_make_helper<seastar::queue<std::optional<int>>, false>::make<int>(int&&) /home/xemul/src/seastar/include/seastar/core/shared_ptr.hh:665:30
    #2 0x7a5616 in seastar::shared_ptr<seastar::queue<std::optional<int>>> seastar::make_shared<seastar::queue<std::optional<int>>, int>(int&&) /home/xemul/src/seastar/include/seastar/core/shared_ptr.hh:684:12
    #3 0x70497e in my_generator() (.resume) /home/xemul/src/seastar/tests/unit/coroutines_test.cc:556:14

line 556 here is the auto q = make_shared<queue<std::optional<int>>>(16); one

Indirect leak of 136 byte(s) in 1 object(s) allocated from:
    #0 0x582641 in operator new(unsigned long) (/home/xemul/src/seastar/build/debug/tests/unit/coroutines_test+0x582641) (BuildId: 7560442d38b7f9121245a32bf098080d3a5f56a1)
    #1 0x837e7f in seastar::future<void> seastar::sleep<std::chrono::_V2::steady_clock, long, std::ratio<1l, 1l>>(std::chrono::duration<long, std::ratio<1l, 1l>>) /home/xemul/src/seastar/include/seastar/core/sleep.hh:58:18
    #2 0x62182a in my_generator()::$_0::operator()() const /home/xemul/src/seastar/tests/unit/coroutines_test.cc:558:16

line 558 is the return sleep(1s); one

and few more

Making the test do co_await gen() in a loop until the generator drains itself solves leaks

@xemul
Copy link
Contributor Author

xemul commented Apr 15, 2024

Cc @tchaikov

@tchaikov tchaikov self-assigned this Apr 15, 2024
tchaikov added a commit to tchaikov/seastar that referenced this issue May 4, 2024
this generator implementation is inspired by https://wg21.link/P2502R2.

Refs scylladb#2190
Refs scylladb#1913
Refs scylladb#1677
Signed-off-by: Kefu Chai <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants