diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index ae4a0b337..6dfb27002 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -44,11 +44,14 @@ pub unsafe extern "C" fn dc_context_new( Box::into_raw(Box::new(ctx)) } +/// Release the context structure. +/// +/// This function releases the memory of the `dc_context_t` structure. #[no_mangle] pub unsafe extern "C" fn dc_context_unref(context: *mut dc_context_t) { assert!(!context.is_null()); let context = &mut *context; - context::dc_context_unref(context); + context::dc_close(context); Box::from_raw(context); } diff --git a/examples/repl/main.rs b/examples/repl/main.rs index c3a47ccec..c89ce9104 100644 --- a/examples/repl/main.rs +++ b/examples/repl/main.rs @@ -456,12 +456,6 @@ fn main_0(args: Vec) -> Result<(), failure::Error> { println!("history saved"); { stop_threads(&ctx.read().unwrap()); - - unsafe { - let mut ctx = ctx.write().unwrap(); - dc_close(&mut ctx); - dc_context_unref(&mut ctx); - } } Ok(()) diff --git a/src/context.rs b/src/context.rs index 3f2944e5a..619d26355 100644 --- a/src/context.rs +++ b/src/context.rs @@ -20,7 +20,6 @@ use crate::sql::Sql; use crate::types::*; use crate::x::*; -#[repr(C)] pub struct Context { pub userdata: *mut libc::c_void, pub dbfile: Arc>, @@ -77,6 +76,14 @@ impl Context { } } +impl Drop for Context { + fn drop(&mut self) { + unsafe { + dc_close(&self); + } + } +} + impl Default for RunningState { fn default() -> Self { RunningState { @@ -165,16 +172,6 @@ pub fn dc_context_new( } } -#[cfg(test)] -mod tests { - use super::*; - #[test] - fn no_crashes_on_context_deref() { - let mut ctx = dc_context_new(None, std::ptr::null_mut(), Some("Test OS".into())); - unsafe { dc_context_unref(&mut ctx) }; - } -} - unsafe fn cb_receive_imf( context: &Context, imf_raw_not_terminated: *const libc::c_char, @@ -258,12 +255,6 @@ fn cb_get_config(context: &Context, key: &str) -> Option { context.sql.get_config(context, key) } -pub unsafe fn dc_context_unref(context: &mut Context) { - if 0 != dc_is_open(context) { - dc_close(context); - } -} - pub unsafe fn dc_close(context: &Context) { info!(context, 0, "disconnecting INBOX-watch",); context.inbox.read().unwrap().disconnect(context); @@ -591,3 +582,24 @@ pub fn dc_is_mvbox(context: &Context, folder_name: impl AsRef) -> bool { false } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn no_crashes_on_context_deref() { + let ctx = dc_context_new(None, std::ptr::null_mut(), Some("Test OS".into())); + std::mem::drop(ctx); + } + + #[test] + fn test_context_double_close() { + let ctx = dc_context_new(None, std::ptr::null_mut(), None); + unsafe { + dc_close(&ctx); + dc_close(&ctx); + } + std::mem::drop(ctx); + } +}