Spawning and then aborting an uncompleted task leaks memory (presumably the future of the task).
use std::time::Duration;
use glib::timeout_future;
fn main() {
let c = glib::MainContext::default();
let l = glib::MainLoop::new(Some(&c), false);
let l_clone = l.clone();
c.spawn_local(async move {
for _ in 0..1000 {
// Spawn a task
let handle = glib::MainContext::ref_thread_default().spawn_local(async {
let test: u128 = std::future::pending().await;
println!("{test}");
});
// Abort task => LEAK!
handle.abort();
}
// Wait 1s and then quit
timeout_future(Duration::from_secs(1)).await;
l_clone.quit();
});
l.run();
}
Backtrace
I'm using valgrind --suppressions=/usr/share/glib-2.0/valgrind/glib.supp --suppressions=/usr/share/gtk-4.0/valgrind/gtk.supp --leak-check=full BINARY_NAME to detect the leaks.
❯ valgrind --suppressions=/usr/share/glib-2.0/valgrind/glib.supp --suppressions=/usr/share/gtk-4.0/valgrind/gtk.supp --leak-check=full ../target/debug/memory_leak
==71348== Memcheck, a memory error detector
==71348== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==71348== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==71348== Command: ../target/debug/memory_leak
==71348==
==71348==
==71348== HEAP SUMMARY:
==71348== in use at exit: 142,440 bytes in 1,271 blocks
==71348== total heap usage: 7,683 allocs, 6,412 frees, 519,309 bytes allocated
==71348==
==71348== 104,000 bytes in 1,000 blocks are definitely lost in loss record 251 of 251
==71348== at 0x484280F: malloc (vg_replace_malloc.c:442)
==71348== by 0x116BDF: alloc (alloc.rs:98)
==71348== by 0x116BDF: alloc::alloc::Global::alloc_impl (alloc.rs:181)
==71348== by 0x116956: allocate (alloc.rs:241)
==71348== by 0x116956: alloc::alloc::exchange_malloc (alloc.rs:330)
==71348== by 0x11EE91: new<alloc::sync::ArcInner<futures_channel::oneshot::Inner<core::result::Result<alloc::boxed::Box<dyn core::any::Any, alloc::alloc::Global>, alloc::boxed::Box<(dyn core::any::Any + core::marker::Send), alloc::alloc::Global>>>>> (boxed.rs:217)
==71348== by 0x11EE91: alloc::sync::Arc<T>::new (sync.rs:389)
==71348== by 0x119417: futures_channel::oneshot::channel (oneshot.rs:105)
==71348== by 0x115366: glib::main_context_futures::<impl glib::auto::main_context::MainContext>::spawn_local_with_priority (main_context_futures.rs:566)
==71348== by 0x11508A: glib::main_context_futures::<impl glib::auto::main_context::MainContext>::spawn_local (main_context_futures.rs:526)
==71348== by 0x113230: memory_leak::main::{{closure}} (main.rs:13)
==71348== by 0x113CE5: glib::main_context_futures::<impl glib::auto::main_context::MainContext>::spawn_local_with_priority::{{closure}} (main_context_futures.rs:564)
==71348== by 0x11636F: <futures_task::future_obj::LocalFutureObj<T> as core::future::future::Future>::poll (future_obj.rs:84)
==71348== by 0x119E0C: <glib::main_context_futures::FutureWrapper as core::future::future::Future>::poll (main_context_futures.rs:38)
==71348== by 0x11CAB9: glib::main_context_futures::TaskSource::poll::{{closure}}::{{closure}} (main_context_futures.rs:245)
==71348==
==71348== LEAK SUMMARY:
==71348== definitely lost: 104,000 bytes in 1,000 blocks
==71348== indirectly lost: 0 bytes in 0 blocks
==71348== possibly lost: 0 bytes in 0 blocks
==71348== still reachable: 19,176 bytes in 41 blocks
==71348== suppressed: 17,248 bytes in 209 blocks
==71348== Reachable blocks (those to which a pointer was found) are not shown.
==71348== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==71348==
==71348== For lists of detected and suppressed errors, rerun with: -s
==71348== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
The bug first appeared in https://github.com/Relm4/Relm4/issues/619, but seems to be located in the glib crate rather than Relm4.
Bug description
Spawning and then aborting an uncompleted task leaks memory (presumably the future of the task).
Backtrace
I'm using
valgrind --suppressions=/usr/share/glib-2.0/valgrind/glib.supp --suppressions=/usr/share/gtk-4.0/valgrind/gtk.supp --leak-check=full BINARY_NAME
to detect the leaks.