summary refs log tree commit diff
path: root/ripple/minitrace/src/pidfd.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ripple/minitrace/src/pidfd.rs')
-rw-r--r--ripple/minitrace/src/pidfd.rs67
1 files changed, 67 insertions, 0 deletions
diff --git a/ripple/minitrace/src/pidfd.rs b/ripple/minitrace/src/pidfd.rs
new file mode 100644
index 0000000..ede0524
--- /dev/null
+++ b/ripple/minitrace/src/pidfd.rs
@@ -0,0 +1,67 @@
+// SPDX-FileCopyrightText: edef <edef@unfathomable.blue>
+// SPDX-License-Identifier: OSL-3.0
+
+use {
+	nix::{libc::close, sys::signal::Signal, unistd::Pid, Result},
+	std::os::unix::prelude::*,
+};
+
+#[derive(Debug)]
+pub struct PidFd {
+	lower: RawFd,
+}
+
+impl PidFd {
+	pub fn open(pid: Pid) -> Result<PidFd> {
+		lower::pidfd_open(pid).map(|lower| PidFd { lower })
+	}
+
+	pub fn kill(&self, signal: Signal) -> nix::Result<()> {
+		unsafe { lower::pidfd_send_signal(self.lower, signal) }
+	}
+}
+
+impl Drop for PidFd {
+	fn drop(&mut self) {
+		unsafe {
+			close(self.lower);
+		}
+	}
+}
+
+mod lower {
+	use {
+		nix::{
+			libc::{c_int, c_uint, c_void, syscall, SYS_pidfd_open, SYS_pidfd_send_signal},
+			sys::signal::Signal,
+			unistd::Pid,
+			Error, Result,
+		},
+		std::{os::unix::prelude::*, ptr},
+	};
+
+	pub fn pidfd_open(pid: Pid) -> Result<RawFd> {
+		unsafe {
+			let pid = pid.as_raw();
+			let ret = syscall(SYS_pidfd_open, pid, 0);
+			if ret >= 0 {
+				Ok(ret as RawFd)
+			} else {
+				Err(Error::last())
+			}
+		}
+	}
+
+	pub unsafe fn pidfd_send_signal(pidfd: RawFd, signal: Signal) -> Result<()> {
+		let signal = signal as c_int;
+		let info: *const c_void = ptr::null();
+		let flags: c_uint = 0;
+
+		let ret = syscall(SYS_pidfd_send_signal, pidfd, signal, info, flags);
+		if ret == 0 {
+			Ok(())
+		} else {
+			Err(Error::last())
+		}
+	}
+}