diff --git a/.github/workflows/ci-preemptive.sh b/.github/workflows/ci-preemptive.sh
index fa2fe6d5..2784991b 100644
--- a/.github/workflows/ci-preemptive.sh
+++ b/.github/workflows/ci-preemptive.sh
@@ -7,7 +7,7 @@ if [ "${CROSS}" = "1" ]; then
export CARGO_NET_RETRY=5
export CARGO_NET_TIMEOUT=10
- cargo install cross --git https://github.com/cross-rs/cross --rev 4090beca3cfffa44371a5bba524de3a578aa46c3
+ cargo install cross --git https://github.com/cross-rs/cross --rev c7dee4d008475ce1c140773cbcd6078f4b86c2aa
CARGO=cross
fi
diff --git a/.github/workflows/ci.sh b/.github/workflows/ci.sh
index f9e4563e..3ebdfb0b 100644
--- a/.github/workflows/ci.sh
+++ b/.github/workflows/ci.sh
@@ -7,7 +7,7 @@ if [ "${CROSS}" = "1" ]; then
export CARGO_NET_RETRY=5
export CARGO_NET_TIMEOUT=10
- cargo install cross --git https://github.com/cross-rs/cross --rev 4090beca3cfffa44371a5bba524de3a578aa46c3
+ cargo install cross --git https://github.com/cross-rs/cross --rev c7dee4d008475ce1c140773cbcd6078f4b86c2aa
CARGO=cross
fi
diff --git a/Cargo.toml b/Cargo.toml
index 6ee406e7..0d93b0ce 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -45,7 +45,7 @@ windows-sys = "0.59"
anyhow = "1.0"
slab = "0.4"
backtrace = "0.3"
-minhook = "0.6"
+minhook = "0.7"
psm = "0.1"
once_cell = "1"
diff --git a/core/docs/en/coroutine.md b/core/docs/en/coroutine.md
index f8a5ab23..faabeca9 100644
--- a/core/docs/en/coroutine.md
+++ b/core/docs/en/coroutine.md
@@ -54,7 +54,7 @@ The above is excerpted from [corosensei](https://github.com/Amanieu/corosensei).
| switch efficiency | ✅ Higher | ❌ High |
| memory usage | ✅ Bytes/KB/MB | ❌ KB/MB |
| scheduled by OS | ❌ | ✅ |
-| stack grow | ✅ | ❌ |
+| grow stack | ✅ | ❌ |
## Stackfull VS Stackless
diff --git a/core/src/co_pool/mod.rs b/core/src/co_pool/mod.rs
index faa75b0b..f9ba8fca 100644
--- a/core/src/co_pool/mod.rs
+++ b/core/src/co_pool/mod.rs
@@ -221,10 +221,7 @@ impl<'p> CoroutinePool<'p> {
match self.state() {
PoolState::Running => {}
PoolState::Stopping | PoolState::Stopped => {
- return Err(Error::new(
- ErrorKind::Other,
- "The coroutine pool is stopping or stopped !",
- ))
+ return Err(Error::other("The coroutine pool is stopping or stopped !"))
}
}
let name = name.unwrap_or(format!("{}@{}", self.name(), uuid::Uuid::new_v4()));
@@ -292,12 +289,11 @@ impl<'p> CoroutinePool<'p> {
let (lock, cvar) = &*arc;
drop(
cvar.wait_timeout_while(
- lock.lock()
- .map_err(|e| Error::new(ErrorKind::Other, format!("{e}")))?,
+ lock.lock().map_err(|e| Error::other(format!("{e}")))?,
wait_time,
|&mut pending| pending,
)
- .map_err(|e| Error::new(ErrorKind::Other, format!("{e}")))?,
+ .map_err(|e| Error::other(format!("{e}")))?,
);
if let Some(r) = self.try_take_task_result(key) {
self.notify(key);
@@ -372,8 +368,7 @@ impl<'p> CoroutinePool<'p> {
"The coroutine pool:{} has reached its maximum size !",
self.name()
);
- return Err(Error::new(
- ErrorKind::Other,
+ return Err(Error::other(
"The coroutine pool has reached its maximum size !",
));
}
@@ -447,12 +442,7 @@ impl<'p> CoroutinePool<'p> {
PoolState::Running | PoolState::Stopping => {
drop(self.try_grow());
}
- PoolState::Stopped => {
- return Err(Error::new(
- ErrorKind::Other,
- "The coroutine pool is stopped !",
- ))
- }
+ PoolState::Stopped => return Err(Error::other("The coroutine pool is stopped !")),
}
Self::init_current(self);
let r = self.try_timeout_schedule(timeout_time);
diff --git a/core/src/co_pool/state.rs b/core/src/co_pool/state.rs
index 6b227cc0..7f6c1ebd 100644
--- a/core/src/co_pool/state.rs
+++ b/core/src/co_pool/state.rs
@@ -1,6 +1,6 @@
use crate::co_pool::CoroutinePool;
use crate::common::constants::PoolState;
-use std::io::{Error, ErrorKind};
+use std::io::Error;
impl CoroutinePool<'_> {
/// running -> stopping
@@ -37,10 +37,11 @@ impl CoroutinePool<'_> {
assert_eq!(old_state, self.state.replace(new_state));
return Ok(old_state);
}
- Err(Error::new(
- ErrorKind::Other,
- format!("{} unexpected {current}->{:?}", self.name(), new_state),
- ))
+ Err(Error::other(format!(
+ "{} unexpected {current}->{:?}",
+ self.name(),
+ new_state
+ )))
}
}
diff --git a/core/src/coroutine/korosensei.rs b/core/src/coroutine/korosensei.rs
index b6eee7ea..ac1b5a54 100644
--- a/core/src/coroutine/korosensei.rs
+++ b/core/src/coroutine/korosensei.rs
@@ -11,7 +11,7 @@ use std::cell::{Cell, RefCell, UnsafeCell};
use std::collections::VecDeque;
use std::ffi::c_longlong;
use std::fmt::Debug;
-use std::io::{Error, ErrorKind};
+use std::io::Error;
cfg_if::cfg_if! {
if #[cfg(unix)] {
@@ -452,10 +452,10 @@ where
CoroutineState::Syscall(y, syscall, state) => {
Ok(CoroutineState::Syscall(y, syscall, state))
}
- _ => Err(Error::new(
- ErrorKind::Other,
- format!("{} unexpected state {current}", self.name()),
- )),
+ _ => Err(Error::other(format!(
+ "{} unexpected state {current}",
+ self.name()
+ ))),
}
}
CoroutineResult::Return(result) => {
diff --git a/core/src/coroutine/state.rs b/core/src/coroutine/state.rs
index 37c64f77..4ff97827 100644
--- a/core/src/coroutine/state.rs
+++ b/core/src/coroutine/state.rs
@@ -4,7 +4,7 @@ use crate::coroutine::listener::Listener;
use crate::coroutine::Coroutine;
use crate::{error, info};
use std::fmt::Debug;
-use std::io::{Error, ErrorKind};
+use std::io::Error;
impl Coroutine<'_, Param, Yield, Return>
where
@@ -45,14 +45,11 @@ where
}
_ => {}
}
- Err(Error::new(
- ErrorKind::Other,
- format!(
- "{} unexpected {current}->{:?}",
- self.name(),
- CoroutineState::::Ready
- ),
- ))
+ Err(Error::other(format!(
+ "{} unexpected {current}->{:?}",
+ self.name(),
+ CoroutineState::::Ready
+ )))
}
/// ready -> running
@@ -87,14 +84,11 @@ where
}
_ => {}
}
- Err(Error::new(
- ErrorKind::Other,
- format!(
- "{} unexpected {current}->{:?}",
- self.name(),
- CoroutineState::::Running
- ),
- ))
+ Err(Error::other(format!(
+ "{} unexpected {current}->{:?}",
+ self.name(),
+ CoroutineState::::Running
+ )))
}
/// running -> suspend
@@ -109,14 +103,11 @@ where
self.on_suspend(self, old_state);
return Ok(());
}
- Err(Error::new(
- ErrorKind::Other,
- format!(
- "{} unexpected {current}->{:?}",
- self.name(),
- CoroutineState::::Suspend(val, timestamp)
- ),
- ))
+ Err(Error::other(format!(
+ "{} unexpected {current}->{:?}",
+ self.name(),
+ CoroutineState::::Suspend(val, timestamp)
+ )))
}
/// running -> syscall
@@ -148,14 +139,11 @@ where
}
_ => {}
}
- Err(Error::new(
- ErrorKind::Other,
- format!(
- "{} unexpected {current}->{:?}",
- self.name(),
- CoroutineState::::Syscall(val, syscall, syscall_state)
- ),
- ))
+ Err(Error::other(format!(
+ "{} unexpected {current}->{:?}",
+ self.name(),
+ CoroutineState::::Syscall(val, syscall, syscall_state)
+ )))
}
/// running -> complete
@@ -170,14 +158,11 @@ where
self.on_complete(self, old_state, val);
return Ok(());
}
- Err(Error::new(
- ErrorKind::Other,
- format!(
- "{} unexpected {current}->{:?}",
- self.name(),
- CoroutineState::::Complete(val)
- ),
- ))
+ Err(Error::other(format!(
+ "{} unexpected {current}->{:?}",
+ self.name(),
+ CoroutineState::::Complete(val)
+ )))
}
/// running -> error
@@ -192,14 +177,11 @@ where
self.on_error(self, old_state, msg);
return Ok(());
}
- Err(Error::new(
- ErrorKind::Other,
- format!(
- "{} unexpected {current}->{:?}",
- self.name(),
- CoroutineState::::Error(msg)
- ),
- ))
+ Err(Error::other(format!(
+ "{} unexpected {current}->{:?}",
+ self.name(),
+ CoroutineState::::Error(msg)
+ )))
}
}
diff --git a/core/src/net/operator/windows/mod.rs b/core/src/net/operator/windows/mod.rs
index a871d7cc..b68f3f6c 100644
--- a/core/src/net/operator/windows/mod.rs
+++ b/core/src/net/operator/windows/mod.rs
@@ -239,7 +239,7 @@ impl<'o> Operator<'o> {
&mut sock_info_len,
) != 0
{
- return Err(Error::new(ErrorKind::Other, "get socket info failed"));
+ return Err(Error::other("get socket info failed"));
}
self.add_handle(fd as HANDLE)?;
let socket = WSASocketW(
@@ -251,10 +251,7 @@ impl<'o> Operator<'o> {
WSA_FLAG_OVERLAPPED,
);
if INVALID_SOCKET == socket {
- return Err(Error::new(
- ErrorKind::Other,
- format!("add {syscall_name} operation failed"),
- ));
+ return Err(Error::other(format!("add {syscall_name} operation failed")));
}
let size = size_of::()
.saturating_add(16)
@@ -370,10 +367,9 @@ impl<'o> Operator<'o> {
{
let errno = WSAGetLastError();
if WSA_IO_PENDING != errno {
- return Err(Error::new(
- ErrorKind::Other,
- format!("add {syscall_name} operation failed with {errno}"),
- ));
+ return Err(Error::other(format!(
+ "add {syscall_name} operation failed with {errno}"
+ )));
}
}
eprintln!("add {syscall_name} operation:{overlapped}");
@@ -464,10 +460,9 @@ impl<'o> Operator<'o> {
{
let errno = WSAGetLastError();
if WSA_IO_PENDING != errno {
- return Err(Error::new(
- ErrorKind::Other,
- format!("add {syscall_name} operation failed with {errno}"),
- ));
+ return Err(Error::other(format!(
+ "add {syscall_name} operation failed with {errno}"
+ )));
}
}
eprintln!("add {syscall_name} operation:{overlapped}");
diff --git a/core/src/scheduler.rs b/core/src/scheduler.rs
index a5edc24c..14ac0347 100644
--- a/core/src/scheduler.rs
+++ b/core/src/scheduler.rs
@@ -9,7 +9,7 @@ use crate::{co, impl_current_for, impl_display_by_debug, impl_for_named};
use dashmap::DashMap;
use std::collections::{BinaryHeap, HashMap, VecDeque};
use std::ffi::c_longlong;
-use std::io::{Error, ErrorKind};
+use std::io::Error;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;
@@ -318,8 +318,7 @@ impl<'s> Scheduler<'s> {
);
}
_ => {
- return Err(Error::new(
- ErrorKind::Other,
+ return Err(Error::other(
"try_timeout_schedule should never execute to here",
));
}
diff --git a/core/tests/coroutine.rs b/core/tests/coroutine.rs
index 11c3eaae..685d01a0 100644
--- a/core/tests/coroutine.rs
+++ b/core/tests/coroutine.rs
@@ -23,10 +23,7 @@ fn coroutine_panic() -> std::io::Result<()> {
})?;
match coroutine.resume()? {
CoroutineState::Error(_) => Ok(()),
- _ => Err(std::io::Error::new(
- std::io::ErrorKind::Other,
- "The coroutine should panic",
- )),
+ _ => Err(std::io::Error::other("The coroutine should panic")),
}
}
@@ -233,8 +230,7 @@ fn coroutine_preemptive() -> std::io::Result<()> {
)
.unwrap();
if result.1.timed_out() {
- Err(std::io::Error::new(
- std::io::ErrorKind::Other,
+ Err(std::io::Error::other(
"The monitor should send signals to coroutines in running state",
))
} else {
@@ -279,8 +275,7 @@ fn coroutine_syscall_not_preemptive() -> std::io::Result<()> {
if result.1.timed_out() {
Ok(())
} else {
- Err(std::io::Error::new(
- std::io::ErrorKind::Other,
+ Err(std::io::Error::other(
"The monitor should not send signals to coroutines in syscall state",
))
}
diff --git a/hook/docs/cn/hook.md b/hook/docs/cn/hook.md
new file mode 100644
index 00000000..dfe9f352
--- /dev/null
+++ b/hook/docs/cn/hook.md
@@ -0,0 +1,67 @@
+---
+title: Hook总览
+date: 2025-01-20 10:00:00
+author: loongs-zhang
+---
+
+# Hook总览
+
+## 为什么hook?
+
+在`Coroutine::resume_with`之后,一个协程可能会长时间占用调度线程(例如,陷入重度计算或系统调用),从而拖慢被该线程调度的其他协程。为了解决陷入系统调用的问题,我们引入hook机制,这样当协程进入系统调用时,它会被自动挂起,从而让其他协程执行。
+
+这带来了一个新问题,`preemptive`特性会`发送大量信号`,而`信号会中断正在执行的系统调用`。此外,由于大多数用户在代码中未处理信号,因此如果他们直接使用`open-routine-core`并且启用`preemptive`特性将导致`灾难性后果`。
+
+## 什么是hook?
+
+Hook可以通过在运行时插入自定义代码来修改或扩展现有代码的行为,甚至可以监控、拦截、修改和重定向系统调用。现在,让我们用一个[例子](https://github.com/loongs-zhang/link-example)来直观地体验它。
+
+假设我们有以下测试代码:
+
+```rust
+use std::time::{Duration, Instant};
+
+#[test]
+fn test_hook() {
+ let start = Instant::now();
+ std::thread::sleep(Duration::MAX);
+ let cost = Instant::now().duration_since(start);
+ println!("cost: {:?}", cost);
+}
+```
+
+如果我们不hook,因为`std::thread::sleep(Duration::MAX)`,这个测试几乎永远不会结束,但有了hook,我们可以在`不更改测试代码`的情况下将`nanosleep`系统调用重定向到[我们的自定义代码](https://github.com/loongs-zhang/link-example/blob/master/dep/src/lib.rs),然后测试就会[很快结束](https://github.com/loongs-zhang/link-example/actions/runs/12862762378/job/35858206179)。
+
+
+

+
+
+## 工作原理
+
+```mermaid
+sequenceDiagram
+ Actor Your Project
+ participant open-coroutine
+ participant open-coroutine-hook
+ participant open-coroutine-core
+
+ Your Project ->> open-coroutine: depends on
+ open-coroutine ->> open-coroutine-hook: depends on
+ alt at compile time
+ open-coroutine ->> open-coroutine: build open-coroutine-hook into dylib
+ open-coroutine ->> open-coroutine: link open-coroutine-hook's dylib
+ else runtime
+ Your Project -->> Operation System: logic execute syscall
+ alt what actually happened
+ Your Project ->> open-coroutine-hook: redirect syscall to open-coroutine-hook's syscall mod
+ open-coroutine-hook ->> open-coroutine-core: call open-coroutine-core's syscall mod
+ open-coroutine-core ->> Operation System: execute fast syscall actually
+ Operation System ->> open-coroutine-core: return syscall result and errno
+ open-coroutine-core -->> Operation System: maybe execute fast syscall many times
+ open-coroutine-core -->> open-coroutine-core: maybe modify syscall result or errno
+ open-coroutine-core ->> open-coroutine-hook: return syscall result and errno
+ open-coroutine-hook ->> Your Project: return syscall result and errno
+ end
+ Operation System ->> Your Project: return syscall result and errno
+ end
+```
diff --git a/hook/docs/en/hook.md b/hook/docs/en/hook.md
index 0b4544c6..cdd6e15d 100644
--- a/hook/docs/en/hook.md
+++ b/hook/docs/en/hook.md
@@ -8,17 +8,14 @@ author: loongs-zhang
## Why hook?
-After a `Coroutine::resume_with`, a coroutine may occupy the scheduling thread for a long time, thereby slowing down
-other coroutines scheduled by that scheduling thread. To solve this problem, we introduce hook, which automatically
-suspends coroutines entering syscall and allow other coroutines to execute.
+After a `Coroutine::resume_with`, a coroutine may occupy the scheduling thread for a long time (e.g. getting stuck in
+heavy computing or syscall), thereby slowing down other coroutines scheduled by that scheduling thread. To solve the
+problem of getting stuck in syscall, we introduce hook, which automatically suspends coroutines that enter syscall and
+allow other coroutines to execute.
-The coroutine occupies scheduling threads for a long time in two scenarios: getting stuck in heavy computing or syscall.
-The following only solves the problem of getting stuck in syscall.
-
-Another problem is that `signals can interrupt the running syscall`, and the `preemptive` feature mechanism sends a
-large
-number of signals. In addition, most user code does not handle signals, if they directly use `open-routine-core` and
-enabling preemptive will lead to `catastrophic consequences`.
+This brings a new problem, the `preemptive` feature will send a large number of signals `which can interrupt the running
+syscall`. In addition, most user code does not handle signals, if they directly use `open-routine-core` and enabling the
+preemptive feature will lead to `catastrophic consequences`.
## What is hook?
@@ -40,8 +37,8 @@ fn test_hook() {
}
```
-If we don't hook, this test would almost never end due to `std::thread::sleep(Duration::MAX)`, but with hook, we
-redirect the `nanosleep` syscall
+If we don't hook, because `std::thread::sleep(Duration::MAX)`, this test almost never ends, but with hook, we redirect
+the `nanosleep` syscall
to [our custom code](https://github.com/loongs-zhang/link-example/blob/master/dep/src/lib.rs) `without change the test
code`, and then the test
will [end soon](https://github.com/loongs-zhang/link-example/actions/runs/12862762378/job/35858206179).
diff --git a/hook/src/syscall/windows.rs b/hook/src/syscall/windows.rs
index 7f154c7c..03264347 100644
--- a/hook/src/syscall/windows.rs
+++ b/hook/src/syscall/windows.rs
@@ -1,5 +1,5 @@
use std::ffi::{c_int, c_longlong, c_uint, c_void};
-use std::io::{Error, ErrorKind};
+use std::io::Error;
use windows_sys::core::{PCSTR, PCWSTR, PSTR};
use windows_sys::Win32::Foundation::{BOOL, HANDLE, TRUE};
use windows_sys::Win32::Networking::WinSock::{
@@ -89,6 +89,5 @@ unsafe fn attach() -> std::io::Result<()> {
// impl_hook!("api-ms-win-core-synch-l1-2-0.dll", WAITONADDRESS, WaitOnAddress(address: *const c_void, compareaddress: *const c_void, addresssize: usize, dwmilliseconds: c_uint) -> BOOL);
// Enable the hook
- minhook::MinHook::enable_all_hooks()
- .map_err(|_| Error::new(ErrorKind::Other, "init all hooks failed !"))
+ minhook::MinHook::enable_all_hooks().map_err(|_| Error::other("init all hooks failed !"))
}
diff --git a/open-coroutine/examples/file_co.rs b/open-coroutine/examples/file_co.rs
index 867a8acb..44a27152 100644
--- a/open-coroutine/examples/file_co.rs
+++ b/open-coroutine/examples/file_co.rs
@@ -42,8 +42,5 @@ pub fn main() -> Result<()> {
if let Some(r) = join_handle.timeout_join(Duration::from_secs(30))? {
return r;
}
- Err(Error::new(
- std::io::ErrorKind::Other,
- "Failed to join the task",
- ))
+ Err(Error::other("Failed to join the task"))
}
diff --git a/open-coroutine/examples/preemptive.rs b/open-coroutine/examples/preemptive.rs
index 7dba535f..a9421589 100644
--- a/open-coroutine/examples/preemptive.rs
+++ b/open-coroutine/examples/preemptive.rs
@@ -74,8 +74,7 @@ pub fn main() -> std::io::Result<()> {
)
.unwrap();
if result.1.timed_out() {
- Err(std::io::Error::new(
- std::io::ErrorKind::Other,
+ Err(std::io::Error::other(
"preemptive schedule failed",
))
} else {
diff --git a/open-coroutine/examples/socket_co.rs b/open-coroutine/examples/socket_co.rs
index 0680b85b..8bf0bf06 100644
--- a/open-coroutine/examples/socket_co.rs
+++ b/open-coroutine/examples/socket_co.rs
@@ -1,5 +1,5 @@
use open_coroutine::task;
-use std::io::{Error, ErrorKind, IoSlice, IoSliceMut, Read, Write};
+use std::io::{Error, IoSlice, IoSliceMut, Read, Write};
use std::net::{Shutdown, TcpListener, ToSocketAddrs};
#[cfg(unix)]
use std::os::fd::AsRawFd;
@@ -175,8 +175,7 @@ pub fn main() -> std::io::Result<()> {
)
.unwrap();
if result.1.timed_out() {
- Err(Error::new(
- ErrorKind::Other,
+ Err(Error::other(
"The coroutine server and coroutine client did not completed within the specified time",
))
} else {
diff --git a/open-coroutine/examples/socket_co_client.rs b/open-coroutine/examples/socket_co_client.rs
index 82df216b..3b595d7a 100644
--- a/open-coroutine/examples/socket_co_client.rs
+++ b/open-coroutine/examples/socket_co_client.rs
@@ -1,5 +1,5 @@
use open_coroutine::task;
-use std::io::{Error, ErrorKind, IoSlice, IoSliceMut, Read, Write};
+use std::io::{Error, IoSlice, IoSliceMut, Read, Write};
use std::net::{Shutdown, TcpListener, ToSocketAddrs};
#[cfg(unix)]
use std::os::fd::AsRawFd;
@@ -170,8 +170,7 @@ pub fn main() -> std::io::Result<()> {
)
.unwrap();
if result.1.timed_out() {
- Err(Error::new(
- ErrorKind::Other,
+ Err(Error::other(
"The coroutine client did not completed within the specified time",
))
} else {
diff --git a/open-coroutine/examples/socket_co_server.rs b/open-coroutine/examples/socket_co_server.rs
index c14d7ed3..ed2d5751 100644
--- a/open-coroutine/examples/socket_co_server.rs
+++ b/open-coroutine/examples/socket_co_server.rs
@@ -1,5 +1,5 @@
use open_coroutine::task;
-use std::io::{Error, ErrorKind, IoSlice, IoSliceMut, Read, Write};
+use std::io::{Error, IoSlice, IoSliceMut, Read, Write};
use std::net::{Shutdown, TcpListener, ToSocketAddrs};
#[cfg(unix)]
use std::os::fd::AsRawFd;
@@ -172,8 +172,7 @@ pub fn main() -> std::io::Result<()> {
)
.unwrap();
if result.1.timed_out() {
- Err(Error::new(
- ErrorKind::Other,
+ Err(Error::other(
"The coroutine service did not completed within the specified time",
))
} else {
diff --git a/open-coroutine/examples/socket_not_co.rs b/open-coroutine/examples/socket_not_co.rs
index c162f006..7e4ef3c2 100644
--- a/open-coroutine/examples/socket_not_co.rs
+++ b/open-coroutine/examples/socket_not_co.rs
@@ -1,4 +1,4 @@
-use std::io::{Error, ErrorKind, IoSlice, IoSliceMut, Read, Write};
+use std::io::{Error, IoSlice, IoSliceMut, Read, Write};
use std::net::{Shutdown, TcpListener, ToSocketAddrs};
#[cfg(unix)]
use std::os::fd::AsRawFd;
@@ -166,8 +166,7 @@ pub fn main() -> std::io::Result<()> {
)
.unwrap();
if result.1.timed_out() {
- Err(Error::new(
- ErrorKind::Other,
+ Err(Error::other(
"The service did not completed within the specified time",
))
} else {
diff --git a/open-coroutine/src/lib.rs b/open-coroutine/src/lib.rs
index b44034e9..cd97324e 100644
--- a/open-coroutine/src/lib.rs
+++ b/open-coroutine/src/lib.rs
@@ -133,8 +133,7 @@ pub fn crate_task R>(
let result: &'static mut std::io::Result = Box::leak(Box::new(
std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| (data.0)(data.1)))
.map_err(|e| {
- Error::new(
- ErrorKind::Other,
+ Error::other(
e.downcast_ref::<&'static str>()
.map_or("task failed without message", |msg| *msg),
)
@@ -165,7 +164,7 @@ impl JoinHandle {
unsafe {
let ptr = task_timeout_join(self, dur.as_nanos().try_into().expect("overflow"));
match ptr.cmp(&0) {
- Ordering::Less => Err(Error::new(ErrorKind::Other, "timeout join failed")),
+ Ordering::Less => Err(Error::other("timeout join failed")),
Ordering::Equal => Ok(None),
Ordering::Greater => Ok(Some((*Box::from_raw(ptr as *mut std::io::Result))?)),
}
@@ -176,7 +175,7 @@ impl JoinHandle {
unsafe {
let ptr = task_join(&self);
match ptr.cmp(&0) {
- Ordering::Less => Err(Error::new(ErrorKind::Other, "join failed")),
+ Ordering::Less => Err(Error::other("join failed")),
Ordering::Equal => Ok(None),
Ordering::Greater => Ok(Some((*Box::from_raw(ptr as *mut std::io::Result))?)),
}
@@ -192,7 +191,7 @@ impl JoinHandle {
for handle in slice {
let left_time = timeout_time.saturating_sub(open_coroutine_core::common::now());
if 0 == left_time {
- return Err(Error::new(ErrorKind::Other, "timeout join failed"));
+ return Err(Error::other("timeout join failed"));
}
if let Ok(x) = handle.timeout_join(Duration::from_nanos(left_time).min(SLICE)) {
return Ok(x);