-
Notifications
You must be signed in to change notification settings - Fork 21
Description
So Im using flutter_rust_bridge and I have a StreamSink that send message to Dart every ~50 milliseconds. StreamSink serializes message to Vec<u8> and it is later converted to a DartExternalTypedData that is being posted to Dart via DartPostCObject.
So the problem is that I have an occasional segfault when closing the Flutter application:
Thread 32 Crashed:: Thread 0x0x14b619530
0 libsystem_kernel.dylib 0x1904ab720 __pthread_kill + 8
1 libsystem_pthread.dylib 0x1904e3f70 pthread_kill + 288
2 libsystem_c.dylib 0x1903f0908 abort + 128
3 libsystem_malloc.dylib 0x1902f9e38 malloc_vreport + 896
4 libsystem_malloc.dylib 0x1902fd9bc malloc_report + 64
5 libsystem_malloc.dylib 0x19031c144 find_zone_and_free + 528
6 libflutterwebrtc.dylib 0x10847e2b4 _$LT$alloc..alloc..Global$u20$as$u20$core..alloc..Allocator$GT$::deallocate::h4707bbc82795b3c8 + 132
7 libflutterwebrtc.dylib 0x10847d8e8 alloc::raw_vec::RawVecInner$LT$A$GT$::deallocate::h88be447e750de4c8 + 96
8 libflutterwebrtc.dylib 0x10847e410 _$LT$alloc..raw_vec..RawVec$LT$T$C$A$GT$$u20$as$u20$core..ops..drop..Drop$GT$::drop::hda09f9faaa9c4f5a + 36
9 libflutterwebrtc.dylib 0x10847ca9c core::ptr::drop_in_place$LT$alloc..raw_vec..RawVec$LT$u8$GT$$GT$::h3e85702e083d7e24 + 24
10 libflutterwebrtc.dylib 0x10847ca6c core::ptr::drop_in_place$LT$alloc..vec..Vec$LT$u8$GT$$GT$::h762d7487b55fbe57 + 68
11 libflutterwebrtc.dylib 0x108478704 core::ptr::drop_in_place$LT$alloc..boxed..Box$LT$alloc..vec..Vec$LT$u8$GT$$GT$$GT$::he0dcf7b4e995225a + 32
12 libflutterwebrtc.dylib 0x108475708 core::mem::drop::h6d3cf56b1ececf5f + 28
13 libflutterwebrtc.dylib 0x108477c98 free_zero_copy_buffer_u8 + 64
14 libflutterwebrtc.dylib 0x108479bb8 allo_isolate::ffi::run_destructors::h7ef8dbdce778c75b + 140
15 libflutterwebrtc.dylib 0x1083d8920 allo_isolate::Isolate::post::h91f35f6c05f955ff + 528 (lib.rs:143)
16 libflutterwebrtc.dylib 0x1083eda8c flutter_rust_bridge::rust2dart::sender::Rust2DartSender::send::h0d5268c4230f2b94 + 24 (sender.rs:17)
17 libflutterwebrtc.dylib 0x108357d8c flutter_rust_bridge::stream::stream_sink::StreamSinkBase$LT$T$C$Rust2DartCodec$GT$::add_raw::hd79fa9ece921a353 + 136 (stream_sink.rs:40)
So it segfaults in free_zero_copy_buffer_u8 and the only thing this function does is drop(Box::from_raw(peer.cast::<Vec<u8>()));, so my first guess was that this must be a double free. Which I was able to confirm with additional logging:
vec_to_dart_native_external_typed_data data = 0x6000025844f0, peer: 0x6000027d8840, callback: 0x106072638
free_zero_copy_buffer_u8 _isolate_callback_data = 0x0, peer = 0x6000027d8840, vec = [0, 1, 0, 0, 0, 1, 0, 0, 0], thread = Thread { id: ThreadId(23), name: None, .. }
run_destructors DartExternalTypedData callback = 0x106072638
free_zero_copy_buffer_u8 _isolate_callback_data = 0x6000025844f0, peer = 0x6000027d8840, vec = [], thread = Thread { id: ThreadId(23), name: None, .. }
So what we see here is that free_zero_copy_buffer_u8 callback is called twice for the same vector (peer = 0x6000027d8840). Second call comes from ffi::run_destructors so DartPostCObject returned false. I'm not sure where the first call comes from, but my guess is Dart VM breaks its contract and reclaims CObject despite returning false from post. What you think about this?