Skip to content

Commit ef2dc6e

Browse files
committed
feat: v3.0.4
1 parent 0ba7638 commit ef2dc6e

File tree

6 files changed

+93
-17
lines changed

6 files changed

+93
-17
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "server-manager"
3-
version = "3.0.2"
3+
version = "3.0.4"
44
edition = "2021"
55
authors = ["ltpp-universe <root@ltpp.vip>"]
66
license = "MIT"

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ pub(crate) mod cfg;
22
pub(crate) mod config;
33
pub(crate) mod manager;
44

5+
pub(crate) use manager::constant::*;
56
#[allow(unused_imports)]
67
pub(crate) use std::{
78
fs,

src/manager/constant.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub static RUNNING_AS_DAEMON: &str = "RUNNING_AS_DAEMON";
2+
pub static RUNNING_AS_DAEMON_VALUE: &str = "RUNNING_AS_DAEMON";

src/manager/impl.rs

Lines changed: 87 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ where
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
}

src/manager/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
pub(crate) mod constant;
12
pub(crate) mod r#impl;
23
pub(crate) mod r#type;

0 commit comments

Comments
 (0)