Skip to content

Updating the XMP data of same image concurrently aborts the entire process.  #230

@CeNiEi

Description

@CeNiEi

The following code, which tries to update xmp data of the SAME file concurrently, will sometimes throw SIGABRT with fatal runtime error: Rust cannot catch foreign exceptions.

#[tokio::main]
async fn main() {

    let mut handles = Vec::new();
    
    for i in 0..2 {
        let handle = spawn_blocking(move || {
            let flip = thread_rng().gen_range(1..=8);

            let (mut xmp_file, mut meta) =
                open_file("a/b/c.jpg");

            sleep(std::time::Duration::from_secs(3));
            update(&mut meta, flip);

            sleep(std::time::Duration::from_secs(3));
            write_to_file(&mut xmp_file, &meta);

        });

        handles.push(handle);
    }

    futures::stream::iter(handles)
        .buffer_unordered(4)
        .collect::<Vec<_>>()
        .await
        .into_iter()
        .collect::<Result<Vec<_>, _>>()
        .unwrap();
}

fn open_file(path: impl AsRef<std::path::Path>) -> (XmpFile, XmpMeta) {
    let path = path.as_ref();

    let mut xmp_file = XmpFile::new().unwrap();

    xmp_file
        .open_file(
            &path,
            OpenFileOptions::default()
                .only_xmp()
                .for_update()
                .use_smart_handler(),
        )
        .or_else(|_| {
            xmp_file.open_file(
                &path,
                OpenFileOptions::default()
                    .only_xmp()
                    .for_update()
                    .use_packet_scanning(),
            )
        })
        .unwrap();

    let xmp = xmp_file.xmp().unwrap_or(XmpMeta::new().unwrap());

    (xmp_file, xmp)
}

fn update(meta: &mut XmpMeta, flip: u8) {
    meta.set_property(TIFF, "Orientation", &XmpValue::new(flip.to_string()))
        .unwrap();
}

fn write_to_file(xmp_file: &mut XmpFile, meta: &XmpMeta) {
    xmp_file.put_xmp(meta).unwrap();
    xmp_file.close();
}

I get that it happens when two different instances are trying to write the data to the same file.. but it will be much better to handle the raised c++ exception and return an appropriate rust error.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions