From ffeb26b24a9d8de85d010d3d418073823068b894 Mon Sep 17 00:00:00 2001 From: pedrocarlo Date: Sun, 21 Sep 2025 13:50:36 -0300 Subject: [PATCH] only ever call callbacks once --- core/io/mod.rs | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/core/io/mod.rs b/core/io/mod.rs index 1b8d8a8ad..e537c393d 100644 --- a/core/io/mod.rs +++ b/core/io/mod.rs @@ -3,6 +3,7 @@ use crate::storage::sqlite3_ondisk::WAL_FRAME_HEADER_SIZE; use crate::{BufferPool, CompletionError, Result}; use bitflags::bitflags; use cfg_block::cfg_block; +use parking_lot::Once; use std::cell::RefCell; use std::fmt; use std::ptr::NonNull; @@ -142,6 +143,8 @@ struct CompletionInner { // Thread safe with OnceLock result: std::sync::OnceLock>, needs_link: bool, + /// before calling callback we check if done is true + done: Once, } impl Debug for CompletionType { @@ -169,6 +172,7 @@ impl Completion { completion_type, result: OnceLock::new(), needs_link: false, + done: Once::new(), }), } } @@ -179,6 +183,7 @@ impl Completion { completion_type, result: OnceLock::new(), needs_link: true, + done: Once::new(), }), } } @@ -258,36 +263,33 @@ impl Completion { pub fn complete(&self, result: i32) { let result = Ok(result); - match &self.inner.completion_type { - CompletionType::Read(r) => r.callback(result), - CompletionType::Write(w) => w.callback(result), - CompletionType::Sync(s) => s.callback(result), // fix - CompletionType::Truncate(t) => t.callback(result), - }; - self.inner - .result - .set(None) - .expect("result must be set only once"); + self.callback(result); } pub fn error(&self, err: CompletionError) { let result = Err(err); - match &self.inner.completion_type { - CompletionType::Read(r) => r.callback(result), - CompletionType::Write(w) => w.callback(result), - CompletionType::Sync(s) => s.callback(result), // fix - CompletionType::Truncate(t) => t.callback(result), - }; - self.inner - .result - .set(Some(err)) - .expect("result must be set only once"); + self.callback(result); } pub fn abort(&self) { self.error(CompletionError::Aborted); } + fn callback(&self, result: Result) { + self.inner.done.call_once(|| { + match &self.inner.completion_type { + CompletionType::Read(r) => r.callback(result), + CompletionType::Write(w) => w.callback(result), + CompletionType::Sync(s) => s.callback(result), // fix + CompletionType::Truncate(t) => t.callback(result), + }; + self.inner + .result + .set(result.err()) + .expect("result must be set only once"); + }); + } + /// only call this method if you are sure that the completion is /// a ReadCompletion, panics otherwise pub fn as_read(&self) -> &ReadCompletion {