Skip to content

Commit 7e7f4f5

Browse files
refactor: move IN_FACADE re-entrancy guard from mod.rs to write.rs
The IN_FACADE thread-local and its accessors (in_facade/set_in_facade) are specific to the write hook's re-entrancy prevention. Moved from the generic impl_facade! macro in mod.rs to write.rs where they belong. The generic impl_facade! no longer has IN_FACADE logic — it keeps the state-transition-before-logging reorder for the preemption fix, while write.rs handles its own re-entrancy guard privately. Agent-Logs-Url: https://github.com/acl-dev/open-coroutine/sessions/481d5b61-d175-4f75-ade3-a6f0b5511a71 Co-authored-by: loongs-zhang <38336731+loongs-zhang@users.noreply.github.com>
1 parent c49454d commit 7e7f4f5

2 files changed

Lines changed: 24 additions & 31 deletions

File tree

core/src/syscall/unix/mod.rs

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,6 @@ use dashmap::DashMap;
22
use once_cell::sync::Lazy;
33
use std::ffi::c_int;
44

5-
//防止重入:info!()/error!()内部会调用write(),如果write被hook了,
6-
//会导致无限递归或嵌套状态转换。当检测到重入时,直接调用内部系统调用跳过facade逻辑。
7-
// Re-entrancy guard: info!()/error!() internally call write(). If write is hooked,
8-
// this causes infinite recursion or nested state transitions that corrupt coroutine state.
9-
// When re-entrancy is detected, bypass the facade and call the inner syscall directly.
10-
thread_local! {
11-
static IN_FACADE: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
12-
}
13-
14-
#[inline]
15-
pub fn in_facade() -> bool {
16-
IN_FACADE.get()
17-
}
18-
19-
#[inline]
20-
pub fn set_in_facade(val: bool) {
21-
IN_FACADE.set(val);
22-
}
23-
245
macro_rules! impl_syscall {
256
(
267
$facade_struct_name:ident, $iocp_struct_name: ident, $nio_struct_name: ident, $raw_struct_name: ident,
@@ -116,9 +97,6 @@ macro_rules! impl_facade {
11697
fn_ptr: Option<&extern "C" fn($($arg_type),*) -> $result>,
11798
$($arg: $arg_type),*
11899
) -> $result {
119-
if $crate::syscall::in_facade() {
120-
return self.inner.$syscall(fn_ptr, $($arg, )*);
121-
}
122100
let syscall = $crate::common::constants::SyscallName::$syscall;
123101
//先转换状态再记录日志:co.syscall(Executing)会通过on_state_changed
124102
//移除MonitorListener的NOTIFY_NODE,使monitor不再发送SIGURG。
@@ -129,7 +107,6 @@ macro_rules! impl_facade {
129107
// preventing the monitor from sending SIGURG. If info!() is called
130108
// first while still in Running state, it can take >10ms on slow
131109
// platforms (QEMU), causing SIGURG to fire and preemption live-lock.
132-
$crate::syscall::set_in_facade(true);
133110
if let Some(co) = $crate::scheduler::SchedulableCoroutine::current() {
134111
let new_state = $crate::common::constants::SyscallState::Executing;
135112
if co.syscall((), syscall, new_state).is_err() {
@@ -139,16 +116,13 @@ macro_rules! impl_facade {
139116
}
140117
}
141118
$crate::info!("enter syscall {}", syscall);
142-
$crate::syscall::set_in_facade(false);
143119
let r = self.inner.$syscall(fn_ptr, $($arg, )*);
144-
$crate::syscall::set_in_facade(true);
145120
if let Some(co) = $crate::scheduler::SchedulableCoroutine::current() {
146121
if co.running().is_err() {
147122
$crate::error!("{} change to running state failed !", co.name());
148123
}
149124
}
150125
$crate::info!("exit syscall {} {:?} {}", syscall, r, std::io::Error::last_os_error());
151-
$crate::syscall::set_in_facade(false);
152126
r
153127
}
154128
}

core/src/syscall/unix/write.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
11
use libc::{size_t, ssize_t};
22
use std::ffi::{c_int, c_void};
33

4+
//防止重入:info!()/error!()内部会调用write(),如果write被hook了,
5+
//会导致无限递归或嵌套状态转换。当检测到重入时,直接调用内部系统调用跳过facade逻辑。
6+
// Re-entrancy guard: info!()/error!() internally call write(). If write is hooked,
7+
// this causes infinite recursion or nested state transitions that corrupt coroutine state.
8+
// When re-entrancy is detected, bypass the facade and call the inner syscall directly.
9+
thread_local! {
10+
static IN_FACADE: std::cell::Cell<bool> = const { std::cell::Cell::new(false) };
11+
}
12+
13+
#[inline]
14+
fn in_facade() -> bool {
15+
IN_FACADE.get()
16+
}
17+
18+
#[inline]
19+
fn set_in_facade(val: bool) {
20+
IN_FACADE.set(val);
21+
}
22+
423
trait WriteSyscall {
524
extern "C" fn write(
625
&self,
@@ -43,12 +62,12 @@ impl<I: WriteSyscall> WriteSyscall for WriteSyscallFacade<I> {
4362
// when already inside a facade (re-entrancy guard)
4463
if fd == libc::STDOUT_FILENO
4564
|| fd == libc::STDERR_FILENO
46-
|| crate::syscall::in_facade()
65+
|| in_facade()
4766
{
4867
return self.inner.write(fn_ptr, fd, buf, len);
4968
}
5069
let syscall = crate::common::constants::SyscallName::write;
51-
crate::syscall::set_in_facade(true);
70+
set_in_facade(true);
5271
if let Some(co) = crate::scheduler::SchedulableCoroutine::current() {
5372
let new_state = crate::common::constants::SyscallState::Executing;
5473
if co.syscall((), syscall, new_state).is_err() {
@@ -58,16 +77,16 @@ impl<I: WriteSyscall> WriteSyscall for WriteSyscallFacade<I> {
5877
}
5978
}
6079
crate::info!("enter syscall {}", syscall);
61-
crate::syscall::set_in_facade(false);
80+
set_in_facade(false);
6281
let r = self.inner.write(fn_ptr, fd, buf, len);
63-
crate::syscall::set_in_facade(true);
82+
set_in_facade(true);
6483
if let Some(co) = crate::scheduler::SchedulableCoroutine::current() {
6584
if co.running().is_err() {
6685
crate::error!("{} change to running state failed !", co.name());
6786
}
6887
}
6988
crate::info!("exit syscall {} {:?} {}", syscall, r, std::io::Error::last_os_error());
70-
crate::syscall::set_in_facade(false);
89+
set_in_facade(false);
7190
r
7291
}
7392
}

0 commit comments

Comments
 (0)