diff --git a/Cargo.lock b/Cargo.lock index 5b1030c..00ba403 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -912,6 +912,7 @@ dependencies = [ "md-5", "minecraft-protocol", "named-binary-tag", + "nix", "notify", "pretty_env_logger", "proxy-protocol", @@ -981,6 +982,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg 1.1.0", +] + [[package]] name = "minecraft-protocol" version = "0.1.0" @@ -1090,6 +1100,20 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "nix" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a58d1d356c6597d08cde02c2f09d785b09e28711837b1ed667dc652c08a694" +dependencies = [ + "bitflags", + "cfg-if 1.0.0", + "libc", + "memoffset", + "pin-utils", + "static_assertions", +] + [[package]] name = "notify" version = "4.0.17" @@ -1574,6 +1598,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.10.0" diff --git a/Cargo.toml b/Cargo.toml index 8bd796e..43fe6a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,6 +80,7 @@ async-std = { version = "1.9.0", default-features = false, optional = true } # Feature: lobby md-5 = { version = "0.10", optional = true } uuid = { version = "0.7", optional = true, features = ["v3"] } +nix = "0.26" [target.'cfg(unix)'.dependencies] libc = "0.2" diff --git a/src/os/mod.rs b/src/os/mod.rs index 9f9bfae..db8b05d 100644 --- a/src/os/mod.rs +++ b/src/os/mod.rs @@ -1,17 +1,15 @@ -#[cfg(unix)] -pub mod unix; #[cfg(windows)] pub mod windows; +use nix::{sys::signal, unistd::Pid}; + /// Force kill process. /// /// Results in undefined behavior if PID is invalid. #[allow(unreachable_code)] pub fn force_kill(pid: u32) -> bool { #[cfg(unix)] - unsafe { - return unix::force_kill(pid); - } + return signal::kill(Pid::from_raw(pid as i32), signal::SIGKILL) == Ok(()); #[cfg(windows)] unsafe { @@ -22,18 +20,14 @@ pub fn force_kill(pid: u32) -> bool { } /// Gracefully kill process. -/// /// Results in undefined behavior if PID is invalid. /// /// # Panics -/// /// Panics on platforms other than Unix. #[allow(unreachable_code, dead_code, unused_variables)] pub fn kill_gracefully(pid: u32) -> bool { #[cfg(unix)] - unsafe { - return unix::kill_gracefully(pid); - } + return signal::kill(Pid::from_raw(pid as i32), signal::SIGTERM) == Ok(()); unimplemented!( "gracefully killing Minecraft server process not implemented on non-Unix platforms" @@ -48,9 +42,7 @@ pub fn kill_gracefully(pid: u32) -> bool { #[allow(unreachable_code)] pub fn freeze(pid: u32) -> bool { #[cfg(unix)] - unsafe { - return unix::freeze(pid); - } + return signal::kill(Pid::from_raw(pid as i32), signal::SIGSTOP) == Ok(()); unimplemented!( "Freezing the Minecraft server process is not implemented on non-Unix platforms." @@ -65,9 +57,7 @@ pub fn freeze(pid: u32) -> bool { #[allow(unreachable_code)] pub fn unfreeze(pid: u32) -> bool { #[cfg(unix)] - unsafe { - return unix::unfreeze(pid); - } + return signal::kill(Pid::from_raw(pid as i32), signal::SIGCONT) == Ok(()); unimplemented!( "Unfreezing the Minecraft server process is not implemented on non-Unix platforms." diff --git a/src/os/unix.rs b/src/os/unix.rs deleted file mode 100644 index 05bc5b7..0000000 --- a/src/os/unix.rs +++ /dev/null @@ -1,55 +0,0 @@ -/// Force kill process on Unix by sending `SIGKILL`. -/// -/// This is unsafe because the PID isn't checked. -pub unsafe fn force_kill(pid: u32) -> bool { - debug!(target: "lazymc", "Sending SIGKILL signal to {pid} to kill server"); - let result = libc::kill(pid as i32, libc::SIGKILL); - - if result != 0 { - trace!(target: "lazymc", "SIGKILL failed: {result}"); - } - - result == 0 -} - -/// Gracefully kill process on Unix by sending `SIGTERM`. -/// -/// This is unsafe because the PID isn't checked. -pub unsafe fn kill_gracefully(pid: u32) -> bool { - debug!(target: "lazymc", "Sending SIGTERM signal to {pid} to kill server"); - let result = libc::kill(pid as i32, libc::SIGTERM); - - if result != 0 { - warn!(target: "lazymc", "Sending SIGTERM signal to server failed: {result}"); - } - - result == 0 -} - -/// Freeze process on Unix by sending `SIGSTOP`. -/// -/// This is unsaft because the PIS isn't checked. -pub unsafe fn freeze(pid: u32) -> bool { - debug!(target: "lazymc", "Sending SIGSTOP signal to {pid} to kill server"); - let result = libc::kill(pid as i32, libc::SIGSTOP); - - if result != 0 { - warn!(target: "lazymc", "Sending SIGSTOP signal to server failed: {result}"); - } - - result == 0 -} - -/// Unfreeze process on Unix by sending `SIGCONT`. -/// -/// This is unsaft because the PIS isn't checked. -pub unsafe fn unfreeze(pid: u32) -> bool { - debug!(target: "lazymc", "Sending SIGCONT signal to {pid} to unfreeze server"); - let result = libc::kill(pid as i32, libc::SIGCONT); - - if result != 0 { - warn!(target: "lazymc", "Sending SIGCONT signal to server failed: {result}"); - } - - result == 0 -}