Skip to content

Crash writing PNG from a C++ background thread on macOS Rust 1.84.0 #136043

Closed
@karip

Description

@karip

I'm writing PNG files from a C++ background thread. It used to work on Rust stable 1.83.0, but it crashes on Rust stable 1.84.0 and nightly. I'm using the png crate, but it or its dependencies shouldn't have any code, which would cause the crash.

The crash happens on macOS and Rust 1.84.0 (I tested on arm and intel macs). The program runs without issues on Ubuntu linux Rust 1.84.0. I didn't test Windows. There are no issues writing PNGs from the C++ main thread, but PNG writing crashes on the C++ background thread. If I write the same program in pure Rust without ffi and using Rust threads, then everything works without issues.

Could this be a regression in the Rust standard library? Or is the Rust function called from the C++ background thread in a way that is incompatible with Rust 1.84.0?

Code

Here's a minimal example project as a zip file so that you can see the code and try it yourself: test-cthread-png.zip

I expected to see this happen: Two PNG files should be written to the current folder: 'out-png-1.png' and 'out-png-2.png'

Instead, this happened: Only one PNG file is written: 'out-png-1.png' (on the main thread) and then the program crashes:

Rust PNG writing to 'out-png-1.png'
Waiting thread to finish..
Rust PNG writing to 'out-png-2.png'
zsh: bus error  ./main

Version it worked on

It most recently worked on: Rust 1.83

Version with regression

rustc --version --verbose:

rustc 1.84.0 (9fc6b4312 2025-01-07)
binary: rustc
commit-hash: 9fc6b43126469e3858e2fe86cafb4f0fd5068869
commit-date: 2025-01-07
host: aarch64-apple-darwin
release: 1.84.0
LLVM version: 19.1.5

LLVM Stack Trace

Stack trace of the example project

Process 62208 launched: '/Users/temp/rust/test-cthread-png/main' (arm64)
Rust PNG writing to 'out-png-1.png'
Waiting thread to finish..
Rust PNG writing to 'out-png-2.png'
Process 62208 stopped
* thread #2, stop reason = EXC_BAD_ACCESS (code=2, address=0x16fe036b0)
    frame #0: 0x000000010005a334 main`alloc::boxed::Box$LT$core..mem..maybe_uninit..MaybeUninit$LT$T$GT$$C$A$GT$::write::hf0470a3673d75fd5(boxed=0x0000000000000000, value=<unavailable>) at boxed.rs:1008
   1005	    /// ```
   1006	    #[unstable(feature = "box_uninit_write", issue = "129397")]
   1007	    #[inline]
-> 1008	    pub fn write(mut boxed: Self, value: T) -> Box<T, A> {
   1009	        unsafe {
   1010	            (*boxed).write(value);
   1011	            boxed.assume_init()
Target 0: (main) stopped.

(lldb) thread backtrace
* thread #2, stop reason = EXC_BAD_ACCESS (code=2, address=0x16fe036b0)
  * frame #0: 0x000000010005a334 main`alloc::boxed::Box$LT$core..mem..maybe_uninit..MaybeUninit$LT$T$GT$$C$A$GT$::write::hf0470a3673d75fd5(boxed=0x0000000000000000, value=<unavailable>) at boxed.rs:1008
    frame #1: 0x000000010005a540 main`_$LT$alloc..boxed..Box$LT$T$GT$$u20$as$u20$core..default..Default$GT$::default::h770abf79bd18dfcf at boxed.rs:1733:9
    frame #2: 0x0000000100045818 main`miniz_oxide::deflate::core::DictOxide::new::hf9b523780f33e231(flags=4112) at core.rs:1156:16
    frame #3: 0x000000010004116c main`_$LT$miniz_oxide..deflate..core..CompressorOxide$u20$as$u20$core..default..Default$GT$::default::h98fdbfee01692241 at core.rs:436:19
    frame #4: 0x000000010003dea8 main`_$LT$alloc..boxed..Box$LT$T$GT$$u20$as$u20$core..default..Default$GT$::default::h89b44e0f0b402adf at boxed.rs:1733:39
    frame #5: 0x000000010003ecc8 main`_$LT$flate2..ffi..rust..Deflate$u20$as$u20$flate2..ffi..DeflateBackend$GT$::make::hee247c1da637a407(level=(__0 = 6), zlib_header=true, _window_bits='\x0f') at rust.rs:131:47
    frame #6: 0x000000010003fc8c main`flate2::mem::Compress::new::h1c4d10d7643a257f(level=(__0 = 6), zlib_header=true) at mem.rs:197:20
    frame #7: 0x000000010002d1dc main`flate2::zlib::write::ZlibEncoder$LT$W$GT$::new::h9b8a7495719a8ece(w=Vec<u8, alloc::alloc::Global> @ 0x000000016fe863a8, level=(__0 = 6)) at write.rs:43:40
    frame #8: 0x000000010000c398 main`png::encoder::Writer$LT$W$GT$::write_image_data::h1a6cf982c65de46c(self=0x000000016fe86b98, data=(data_ptr = "", length = 307200)) at encoder.rs:742:32
    frame #9: 0x000000010000b99c main`rspng_write(filenumber='\x02') at lib.rs:20:8
    frame #10: 0x00000001000022fc main`MyThread::run(this=0x000000016fdff32b) at main.cpp:9:13
    frame #11: 0x0000000100002e54 main`decltype(*std::declval<MyThread*>().*std::declval<void (MyThread::*)()>()()) std::__1::__invoke[abi:ne180100]<void (MyThread::*)(), MyThread*, void>(__f=0x0000600002b940c8, __a0=0x0000600002b940d8) at invoke.h:312:25
    frame #12: 0x0000000100002d84 main`void std::__1::__thread_execute[abi:ne180100]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (MyThread::*)(), MyThread*, 2ul>(__t=size=3, (null)=__tuple_indices<2UL> @ 0x000000016fe86f7f) at thread.h:199:3
    frame #13: 0x0000000100002680 main`void* std::__1::__thread_proxy[abi:ne180100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (MyThread::*)(), MyThread*>>(__vp=0x0000600002b940c0) at thread.h:208:3
    frame #14: 0x0000000188b272e4 libsystem_pthread.dylib`_pthread_start + 136
(lldb)

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-external-bugCategory: issue that is caused by bugs in software beyond our control

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions