variant: Fix double-free

gio::Settings::set_value takes over ownership of the Variant sometimes, but in other cases it doesn't. To prevent this being a problem, the custom Variant is made of the type that will never have its ownership taken.

This is not necessarily consistent with what gtk-rs authors intended.

In practice, the ownership is shared by refcounting, and after the Rust reference is dropped, one taken by Settings survives.
This commit is contained in:
Dorota Czaplejewicz
2020-02-03 14:46:49 +00:00
parent 11213ba13a
commit 1cbc21ad11

View File

@ -91,6 +91,11 @@ mod variants {
unsafe { unsafe {
let ret = glib_sys::g_variant_builder_end(builder); let ret = glib_sys::g_variant_builder_end(builder);
glib_sys::g_variant_builder_unref(builder); glib_sys::g_variant_builder_unref(builder);
// HACK: This is to prevent C taking ownership
// of "floating" Variants,
// where Rust gets to keep a stale reference
// and crash when trying to drop it.
glib_sys::g_variant_ref_sink(ret);
glib::Variant::from_glib_full(ret) glib::Variant::from_glib_full(ret)
} }
} }
@ -141,7 +146,7 @@ fn set_layout(kind: String, name: String) {
.chain(inputs).collect(); .chain(inputs).collect();
settings.set_value( settings.set_value(
"sources", "sources",
&variants::ArrayPairString(inputs).to_variant() &variants::ArrayPairString(inputs).to_variant(),
); );
settings.apply(); settings.apply();
} }