5959 /// - `Result<(), Box<dyn std::error::Error>>`: Operation result.
6060 ///
6161 /// This function returns an error because daemon mode is not supported on non-Unix platforms.
62- #[ cfg( unix ) ]
62+ #[ cfg( not ( windows ) ) ]
6363 pub fn start_daemon ( & self ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
64- if std:: env:: var ( " RUNNING_AS_DAEMON" ) . is_ok ( ) {
64+ if std:: env:: var ( RUNNING_AS_DAEMON ) . is_ok ( ) {
6565 self . write_pid_file ( ) ?;
6666 let rt: Runtime = Runtime :: new ( ) ?;
6767 rt. block_on ( async {
@@ -71,18 +71,44 @@ where
7171 }
7272 let exe_path: PathBuf = std:: env:: current_exe ( ) ?;
7373 let mut cmd: Command = Command :: new ( exe_path) ;
74- cmd. env ( " RUNNING_AS_DAEMON" , "1" )
74+ cmd. env ( RUNNING_AS_DAEMON , RUNNING_AS_DAEMON_VALUE )
7575 . stdout ( Stdio :: from ( fs:: File :: create ( & self . config . stdout_log ) ?) )
7676 . stderr ( Stdio :: from ( fs:: File :: create ( & self . config . stderr_log ) ?) )
7777 . stdin ( Stdio :: null ( ) ) ;
7878 cmd. spawn ( ) ?;
7979 exit ( 0 ) ;
8080 }
8181
82- /// 在非 Unix 平台下返回错误。
83- #[ cfg( not( unix) ) ]
82+ #[ cfg( windows) ]
83+ /// Start the server in daemon (background) mode on Windows platforms
84+ /// Title: Start the server in daemon mode on Windows platforms
85+ ///
86+ /// Parameters:
87+ /// - None
88+ ///
89+ /// Returns:
90+ /// - `Result<(), Box<dyn std::error::Error>>`: Operation result.
91+ ///
92+ /// This function starts a detached process on Windows using Windows API.
8493 pub fn start_daemon ( & self ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
85- Err ( "Daemon mode is not supported on non-Unix platforms" . into ( ) )
94+ use std:: os:: windows:: process:: CommandExt ;
95+ if std:: env:: var ( RUNNING_AS_DAEMON ) . is_ok ( ) {
96+ self . write_pid_file ( ) ?;
97+ let rt: Runtime = Runtime :: new ( ) ?;
98+ rt. block_on ( async {
99+ ( self . server_fn ) ( ) . await ;
100+ } ) ;
101+ return Ok ( ( ) ) ;
102+ }
103+ let exe_path: PathBuf = std:: env:: current_exe ( ) ?;
104+ let mut cmd: Command = Command :: new ( exe_path) ;
105+ cmd. env ( RUNNING_AS_DAEMON , RUNNING_AS_DAEMON_VALUE )
106+ . stdout ( Stdio :: from ( fs:: File :: create ( & self . config . stdout_log ) ?) )
107+ . stderr ( Stdio :: from ( fs:: File :: create ( & self . config . stderr_log ) ?) )
108+ . stdin ( Stdio :: null ( ) )
109+ . creation_flags ( 0x00000008 ) ;
110+ cmd. spawn ( ) ?;
111+ std:: process:: exit ( 0 ) ;
86112 }
87113
88114 /// Title: Read process ID from the PID file
@@ -127,7 +153,7 @@ where
127153 /// - `Result<(), Box<dyn std::error::Error>>`: Operation result.
128154 ///
129155 /// This function sends a SIGTERM signal to the process with the given PID using libc::kill.
130- #[ cfg( unix ) ]
156+ #[ cfg( not ( windows ) ) ]
131157 fn kill_process ( & self , pid : i32 ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
132158 let result: Result < std:: process:: Output , std:: io:: Error > = Command :: new ( "kill" )
133159 . arg ( "-TERM" )
@@ -145,18 +171,64 @@ where
145171 }
146172 }
147173
148- /// Title: Kill process by PID on non-Unix platforms
174+ #[ cfg( windows) ]
175+ /// Kill process by PID on Windows platforms
176+ /// Title: Kill process by PID on Windows platforms
149177 ///
150178 /// Parameters:
151- /// - `pid`: The process ID to kill.
179+ /// - `` pid` `: The process ID to kill.
152180 ///
153181 /// Returns:
154- /// - `Result<(), Box<dyn std::error::Error>>`: Operation result.
182+ /// - `` Result<(), Box<dyn std::error::Error>>` `: Operation result.
155183 ///
156- /// This function returns an error because killing a process is not supported on non-Unix platforms.
157-
158- #[ cfg( not( unix) ) ]
159- fn kill_process ( & self , _pid : i32 ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
160- Err ( "kill_process is not supported on non-Unix platforms" . into ( ) )
184+ /// This function attempts to kill the process with the given PID using Windows API.
185+ /// If opening or terminating the process fails, the detailed error code is returned.
186+ fn kill_process ( & self , pid : i32 ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
187+ use std:: ffi:: c_void;
188+ type DWORD = u32 ;
189+ type BOOL = i32 ;
190+ type HANDLE = * mut c_void ;
191+ type UINT = u32 ;
192+ const PROCESS_TERMINATE : DWORD = 0x0001 ;
193+ const PROCESS_ALL_ACCESS : DWORD = 0x1F0FFF ;
194+ extern "system" {
195+ fn OpenProcess (
196+ dwDesiredAccess : DWORD ,
197+ bInheritHandle : BOOL ,
198+ dwProcessId : DWORD ,
199+ ) -> HANDLE ;
200+ fn TerminateProcess ( hProcess : HANDLE , uExitCode : UINT ) -> BOOL ;
201+ fn CloseHandle ( hObject : HANDLE ) -> BOOL ;
202+ fn GetLastError ( ) -> DWORD ;
203+ }
204+ let process_id: DWORD = pid as DWORD ;
205+ let mut process_handle: HANDLE = unsafe { OpenProcess ( PROCESS_TERMINATE , 0 , process_id) } ;
206+ if process_handle. is_null ( ) {
207+ process_handle = unsafe { OpenProcess ( PROCESS_ALL_ACCESS , 0 , process_id) } ;
208+ }
209+ if process_handle. is_null ( ) {
210+ let error_code = unsafe { GetLastError ( ) } ;
211+ return Err ( format ! (
212+ "Failed to open process with pid: {}. Error code: {}" ,
213+ pid, error_code
214+ )
215+ . into ( ) ) ;
216+ }
217+ let terminate_result: BOOL = unsafe { TerminateProcess ( process_handle, 1 ) } ;
218+ if terminate_result == 0 {
219+ let error_code = unsafe { GetLastError ( ) } ;
220+ unsafe {
221+ CloseHandle ( process_handle) ;
222+ }
223+ return Err ( format ! (
224+ "Failed to terminate process with pid: {}. Error code: {}" ,
225+ pid, error_code
226+ )
227+ . into ( ) ) ;
228+ }
229+ unsafe {
230+ CloseHandle ( process_handle) ;
231+ }
232+ Ok ( ( ) )
161233 }
162234}
0 commit comments