rust-windowing / winit

Window handling library in pure Rust
https://docs.rs/winit/
Apache License 2.0
4.7k stars 887 forks source link

checkers: Dangling memory regions detected for EventLoopExtUnix #1487

Open kstrafe opened 4 years ago

kstrafe commented 4 years ago

Using checkers to check for dangling memory leads us to the following simple case.

use checkers;

#[global_allocator]
static ALLOCATOR: checkers::Allocator = checkers::Allocator::system();

#[checkers::test]
fn test() {
    use winit::platform::unix::EventLoopExtUnix;
    winit::event_loop::EventLoop::<()>::new_any_thread();
}

Cargo.toml:

[package]
name = "dangle"
version = "0.1.0"
edition = "2018"

[dependencies]
checkers = "0.5.6"
winit = "0.21.0"

Platform: Linux 5.5.6-1 (Manjaro) running X11 version 11.0, X.Org version: 1.20.6, ran under i3-wm version 4.18 (2020-02-18) Running the above test using cargo test yields:

running 1 test
test test ... FAILED

failures:

---- test stdout ----
Dangling region (0x7fac10006140-0x7fac10006151 (size: 17, align: 1))
Dangling region (0x7fac1000e4a0-0x7fac100105e0 (size: 8512, align: 8))
Dangling region (0x7fac10010800-0x7fac1001080d (size: 13, align: 1))
Dangling region (0x7fac1001cf10-0x7fac10035f20 (size: 102416, align: 16))
Dangling region (0x7fac10035f30-0x7fac10035f3c (size: 12, align: 1))
Dangling region (0x7fac10046700-0x7fac1004670d (size: 13, align: 1))
Dangling region (0x7fac100468d0-0x7fac100468df (size: 15, align: 1))
Dangling region (0x7fac100469f0-0x7fac100469f2 (size: 2, align: 1))
Dangling region (0x7fac10046b40-0x7fac10046c58 (size: 280, align: 8))
Dangling region (0x7fac10046c60-0x7fac10046c79 (size: 25, align: 1))
Dangling region (0x7fac10046cf0-0x7fac10046cfc (size: 12, align: 1))
thread 'test' panicked at 'allocation checks failed', src/lib.rs:6:1
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

failures:
    test

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--lib'
kstrafe commented 4 years ago

Using catch unwind we can panic while letting the unwinder deallocate. Here's one place where we leak 8152 bytes.

    pub fn new_x11_any_thread() -> Result<EventLoop<T>, XNotSupported> {
        let xconn = match X11_BACKEND.lock().as_ref() {
            Ok(xconn) => xconn.clone(),
            Err(err) => return Err(err.clone()),
        };

Adding a panic before this match seems to not trigger the 8512 region:

Dangling region (0x7f4968010d00-0x7f4968010e80 (size: 384, align: 1))

Panic after match:

Dangling region (0x7fa05800e4a0-0x7fa0580105e0 (size: 8512, align: 8))
Dangling region (0x7fa0580105f0-0x7fa058010770 (size: 384, align: 1))

Edit: this might be a static variable issue. See https://github.com/udoprog/checkers/issues/5