diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 1843c4f0b..3842a505c 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -562,9 +562,12 @@ void dc_start_io (dc_context_t* context); int dc_is_io_running(const dc_context_t* context); /** - * Stop job and IMAP/SMTP tasks and return when they are finished. - * If IO is not running, nothing happens. + * Stop job, IMAP, SMTP and other tasks and return when they + * are finished. * To check the current IO state, use dc_is_io_running(). + * Even if IO is not running, there may be pending tasks, + * so this function should always be called before releasing + * context to ensure clean termination of event loop. * * If the context was created by the dc_accounts_t account manager, * use dc_accounts_stop_io() instead of this function. @@ -2373,7 +2376,6 @@ void dc_accounts_start_io (dc_accounts_t* accounts); /** * Stop job and IMAP/SMTP tasks for all accounts and return when they are finished. - * If IO is not running, nothing happens. * This is similar to dc_stop_io(), which, however, * must not be called for accounts handled by the account manager. * diff --git a/src/context.rs b/src/context.rs index b070a3a56..ac7a62b35 100644 --- a/src/context.rs +++ b/src/context.rs @@ -163,10 +163,6 @@ impl Context { /// Stops the IO scheduler. pub async fn stop_io(&self) { info!(self, "stopping IO"); - if !self.is_io_running().await { - info!(self, "IO is not running"); - return; - } self.inner.stop_io().await; } @@ -483,14 +479,19 @@ impl InnerContext { } async fn stop_io(&self) { - assert!(self.is_io_running().await, "context is already stopped"); - let token = { - let lock = &*self.scheduler.read().await; - lock.pre_stop().await - }; - { - let lock = &mut *self.scheduler.write().await; - lock.stop(token).await; + if self.is_io_running().await { + let token = { + let lock = &*self.scheduler.read().await; + lock.pre_stop().await + }; + { + let lock = &mut *self.scheduler.write().await; + lock.stop(token).await; + } + } + + if let Some(ephemeral_task) = self.ephemeral_task.write().await.take() { + ephemeral_task.cancel().await; } } }