Repository: rust
Issue: Crash writing PNG from a C++ background thread on macOS Rust 1.84.0
Labels: C-external-bug

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](https://github.com/Frommi/miniz_oxide/issues/160), 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](https://github.com/user-attachments/files/18545493/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

<details><summary>Stack trace of the example project</summary>
<p>

```
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)
```

</p>
</details>