diff --git a/src/cancel.rs b/src/cancel.rs index 6ad7f864..4ca9c19a 100644 --- a/src/cancel.rs +++ b/src/cancel.rs @@ -34,9 +34,12 @@ pub fn trigger_cancel_panic() -> ! { pub trait CancelIo { type Data; fn new() -> Self; - fn set(&self, _: Self::Data); + // set the io data + fn set(&self, io_data: Self::Data); + // clear the io data fn clear(&self); - unsafe fn cancel(&self); + // if io was set, return Some(io::Result<()>) + unsafe fn cancel(&self) -> Option>; } #[cfg(not(feature = "io_cancel"))] @@ -120,15 +123,19 @@ impl CancelImpl { pub unsafe fn cancel(&self) { self.state.fetch_or(1, Ordering::Release); + if let Some(Ok(())) = self.io.cancel() { + // successfully canceled + return; + } + if let Some(co) = self.co.take() { if let Some(mut co) = co.take() { - self.io.clear(); + // this is not safe, the kernel may still need to use the overlapped // set the cancel result for the coroutine set_co_para(&mut co, io::Error::new(io::ErrorKind::Other, "Canceled")); - return get_scheduler().schedule(co); + get_scheduler().schedule(co); } } - self.io.cancel(); } // clear the cancel bit so that we can reuse the cancel @@ -153,9 +160,7 @@ impl CancelImpl { // clear the cancel io data // should be called after io completion pub fn clear(&self) { - // if self.co.take(Ordering::Acquire).is_none() { self.io.clear(); - // } } } diff --git a/src/io/sys/unix/cancel.rs b/src/io/sys/unix/cancel.rs index 683ade09..4a52bac9 100644 --- a/src/io/sys/unix/cancel.rs +++ b/src/io/sys/unix/cancel.rs @@ -22,11 +22,13 @@ impl CancelIo for CancelIoImpl { self.0.take(); } - unsafe fn cancel(&self) { + unsafe fn cancel(&self) -> Option> { if let Some(e) = self.0.take() { if let Some(co) = e.co.take() { get_scheduler().schedule(co); + return Some(Ok(())); } } + None } } diff --git a/src/io/sys/windows/cancel.rs b/src/io/sys/windows/cancel.rs index d87b6593..e3c0e306 100644 --- a/src/io/sys/windows/cancel.rs +++ b/src/io/sys/windows/cancel.rs @@ -54,7 +54,7 @@ impl CancelIo for CancelIoImpl { self.0.take(); } - unsafe fn cancel(&self) { - self.0.take().map(|d| d.cancel()); + unsafe fn cancel(&self) -> Option> { + self.0.take().map(|d| d.cancel()) } }