@@ -15,9 +15,52 @@ impl_syscall!(WriteSyscallFacade, IoUringWriteSyscall, NioWriteSyscall, RawWrite
1515 write( fd: c_int, buf: * const c_void, len: size_t) -> ssize_t
1616) ;
1717
18- impl_facade ! ( WriteSyscallFacade , WriteSyscall ,
19- write( fd: c_int, buf: * const c_void, len: size_t) -> ssize_t
20- ) ;
18+ //write的facade需要特殊处理:stdout/stderr的write由日志框架(tracing)触发,
19+ //必须跳过所有中间层(facade/io_uring/NIO)直接调用原始系统调用,否则:
20+ //1. facade内部的info!()会再次触发write导致stdout RefCell重复借用(无限递归)
21+ //2. io_uring层会提交写操作并阻塞在condvar等待完成,导致死锁
22+ // The write facade needs special handling: writes to stdout/stderr are
23+ // triggered by the logging framework (tracing). They must bypass ALL layers
24+ // (facade, io_uring, NIO) and call the raw syscall directly. Otherwise:
25+ // 1. The facade's info!() re-triggers write → stdout RefCell double-borrow
26+ // 2. The io_uring layer submits the write and blocks on condvar → deadlock
27+ #[ repr( C ) ]
28+ #[ derive( Debug , Default ) ]
29+ struct WriteSyscallFacade < I : WriteSyscall > {
30+ inner : I ,
31+ }
32+
33+ impl < I : WriteSyscall > WriteSyscall for WriteSyscallFacade < I > {
34+ extern "C" fn write (
35+ & self ,
36+ fn_ptr : Option < & extern "C" fn ( c_int , * const c_void , size_t ) -> ssize_t > ,
37+ fd : c_int ,
38+ buf : * const c_void ,
39+ len : size_t ,
40+ ) -> ssize_t {
41+ let syscall = crate :: common:: constants:: SyscallName :: write;
42+ if let Some ( co) = crate :: scheduler:: SchedulableCoroutine :: current ( ) {
43+ let new_state = crate :: common:: constants:: SyscallState :: Executing ;
44+ if co. syscall ( ( ) , syscall, new_state) . is_err ( ) {
45+ crate :: error!( "{} change to syscall {} {} failed !" ,
46+ co. name( ) , syscall, new_state
47+ ) ;
48+ }
49+ }
50+ if fd == libc:: STDOUT_FILENO || fd == libc:: STDERR_FILENO {
51+ return RawWriteSyscall :: default ( ) . write ( fn_ptr, fd, buf, len) ;
52+ }
53+ crate :: info!( "enter syscall {}" , syscall) ;
54+ let r = self . inner . write ( fn_ptr, fd, buf, len) ;
55+ if let Some ( co) = crate :: scheduler:: SchedulableCoroutine :: current ( ) {
56+ if co. running ( ) . is_err ( ) {
57+ crate :: error!( "{} change to running state failed !" , co. name( ) ) ;
58+ }
59+ }
60+ crate :: info!( "exit syscall {} {:?} {}" , syscall, r, std:: io:: Error :: last_os_error( ) ) ;
61+ r
62+ }
63+ }
2164
2265impl_io_uring_write ! ( IoUringWriteSyscall , WriteSyscall ,
2366 write( fd: c_int, buf: * const c_void, len: size_t) -> ssize_t
0 commit comments