From 4a3d3b3b8c91d550c780a2b030ba6ed03b93911a Mon Sep 17 00:00:00 2001 From: Nikita Sivukhin Date: Thu, 4 Sep 2025 23:48:08 +0400 Subject: [PATCH] mark completion as done only after callback will be executed - otherwise, in multi-threading environment, other thread can think that completion is finished and start execution - this can lead to violated assertions (for example, page must be loaded, but as callback is not executed yet assert will be fired) --- core/io/mod.rs | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/core/io/mod.rs b/core/io/mod.rs index 4b877e37b..33257056c 100644 --- a/core/io/mod.rs +++ b/core/io/mod.rs @@ -226,27 +226,31 @@ impl Completion { } pub fn complete(&self, result: i32) { - if self.inner.result.set(None).is_ok() { - 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), - }; - } + 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"); } pub fn error(&self, err: CompletionError) { - if self.inner.result.set(Some(err)).is_ok() { - 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), - }; - } + 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"); } pub fn abort(&self) {