Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

segfault when using *save_buffer_with_opts and *save_buffer #38

Open
yaa110 opened this issue Jun 19, 2023 · 2 comments
Open

segfault when using *save_buffer_with_opts and *save_buffer #38

yaa110 opened this issue Jun 19, 2023 · 2 comments

Comments

@yaa110
Copy link

yaa110 commented Jun 19, 2023

Please consider the following example:

use libvips::{VipsApp, VipsImage, ops::{JpegsaveBufferOptions, Interpretation}};
use mimalloc::MiMalloc;

#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;

fn main() {
    let app = VipsApp::new(env!("CARGO_PKG_NAME"), false).unwrap();
    app.cache_set_max(0);
    app.cache_set_max_mem(0);
    app.cache_set_max_files(0);
    app.vips_cache_set_trace(false);
    app.vips_cache_set_dump(false);
    app.progress_set(false);
    app.concurrency_set(1);
    app.pipe_read_limit_set(-1);

    let data = std::fs::read("input.jpg").unwrap();
    let mut img = VipsImage::new_from_buffer(data.as_slice(), "").unwrap();
    img = libvips::ops::colourspace(&img, Interpretation::BW).unwrap();
    let output = libvips::ops::jpegsave_buffer_with_opts(
        &img,
        &JpegsaveBufferOptions {
            q: 75,
            interlace: true,
            strip: true,
            ..Default::default()
        },
    ).unwrap();
    std::fs::write("output.jpg", output.as_slice()).unwrap();
}

running the code always causes segfault:

939780 segmentation fault (core dumped)

By removing the MiMalloc it sometimes (randomly) causes segfault.

GDB Backtrace:

#0  0x000055555556187d in mi_free (p=0x5555557518f0) at c_src/mimalloc/src/alloc.c:565
#1  0x000055555555f679 in mimalloc::{impl#0}::dealloc (self=0x5555555ae027, ptr=0x5555557518f0, _layout=...) at /home/yaa110/.cargo/registry/src/index.crates.io-6f17d22bba15001f/mimalloc-0.1.37/src/lib.rs:91
#2  0x000055555555ebf3 in test_vips::_::__rg_dealloc (arg0=0x5555557518f0, arg1=31184, arg2=1) at src/main.rs:5
#3  0x0000555555578840 in alloc::alloc::dealloc (ptr=0x5555557518f0, layout=...) at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/alloc.rs:111
#4  alloc::alloc::{impl#1}::deallocate (self=0x7fffffffd9f0, ptr=..., layout=...) at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/alloc.rs:248
#5  0x0000555555577fbb in alloc::raw_vec::{impl#3}::drop<u8, alloc::alloc::Global> (self=0x7fffffffd9f0) at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/alloc/src/raw_vec.rs:485
#6  0x00005555555753bb in core::ptr::drop_in_place<alloc::raw_vec::RawVec<u8, alloc::alloc::Global>> () at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ptr/mod.rs:490
#7  0x0000555555575294 in core::ptr::drop_in_place<alloc::vec::Vec<u8, alloc::alloc::Global>> () at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/core/src/ptr/mod.rs:490
#8  0x000055555555f985 in std::fs::write<&str, alloc::vec::Vec<u8, alloc::alloc::Global>> (path=..., contents=...) at /rustc/90c541806f23a127002de5b4038be731ba1458ca/library/std/src/fs.rs:330
#9  0x000055555555eb03 in test_vips::main () at src/main.rs:30

GDB backtrace without MiMalloc:

#0  0x00007ffff7c4855d in vips_operation_touch (operation=0x555555710d10) at ../libvips/iofuncs/cache.c:607
#1  0x00007ffff7c485cb in vips_cache_ref (operation=0x555555710d10) at ../libvips/iofuncs/cache.c:625
#2  0x00007ffff7c4865a in vips_cache_insert (operation=0x555555710d10) at ../libvips/iofuncs/cache.c:656
#3  0x00007ffff7c48b9d in vips_cache_operation_add (operation=0x555555710d10) at ../libvips/iofuncs/cache.c:868
#4  0x00007ffff7c48cc7 in vips_cache_operation_buildp (operation=0x7fffffffd4c0) at ../libvips/iofuncs/cache.c:915
#5  0x00007ffff7c528bb in vips_call_required_optional (operation=0x7fffffffd4c0, required=0x7fffffffd510, optional=0x7fffffffd630) at ../libvips/iofuncs/operation.c:913
#6  0x00007ffff7c52a28 in vips_call_by_name (operation_name=0x7ffff7cac5c5 "VipsForeignLoadJpegBuffer", option_string=0x5555556fb250 "", required=0x7fffffffd510, optional=0x7fffffffd630)
    at ../libvips/iofuncs/operation.c:953
#7  0x00007ffff7c53232 in vips_call_split_option_string (operation_name=0x7ffff7cac5c5 "VipsForeignLoadJpegBuffer", option_string=0x5555556fb250 "", optional=0x7fffffffd630) at ../libvips/iofuncs/operation.c:1072
#8  0x00007ffff7c40af0 in vips_image_new_from_buffer (buf=0x555555654160, len=57778, option_string=0x5555556fb250 "") at ../libvips/iofuncs/image.c:2169
#9  0x0000555555563a49 in libvips::image::VipsImage::new_from_buffer (buffer=..., option_str=...) at src/image.rs:125
#11 0x000055555555cafd in test_vips::main () at src/main.rs:30
@yaa110
Copy link
Author

yaa110 commented Jun 19, 2023

The problem has been fixed using the following workaround:

let buf = output.as_ptr();
std::mem::forget(output);
unsafe { glib_sys::g_free(buf as *mut _) };

The memory buffer is allocated using g_malloc in libvips, so it must be freed using g_free.

@yaa110
Copy link
Author

yaa110 commented Jun 19, 2023

Maybe it is better to return a custom struct from these functions:

pub struct VipsOutput(Option<Vec<u8>>);

impl From<Vec<u8>> for VipsOutput {
    fn from(buf: Vec<u8>) -> Self {
        Self(Some(buf))
    }
}

impl Drop for VipsOutput {
    fn drop(&mut self) {
        if let Some(buf) = self.0.take() {
            let ptr = buf.as_ptr();
            std::mem::forget(buf);
            unsafe { glib_sys::g_free(ptr as *mut _) };
        }
    }
}

pub fn jpegsave_buffer(inp: &VipsImage) -> Result<VipsOutput> {}

@yaa110 yaa110 changed the title segfault when using *save_buffer_with_opts segfault when using *save_buffer_with_opts and *save_buffer Jun 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant