Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sys adding subset of procctl support for FreeBSD. #2164

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/2164.added.md
@@ -0,0 +1 @@
Added the `procctl` process feature to `::nix::sys` for FreeBSD.
6 changes: 6 additions & 0 deletions src/sys/mod.rs
Expand Up @@ -73,6 +73,12 @@ feature! {
pub mod prctl;
}

#[cfg(target_os = "freebsd")]
feature! {
#![feature = "process"]
pub mod procctl;
}

feature! {
#![feature = "pthread"]
pub mod pthread;
Expand Down
58 changes: 58 additions & 0 deletions src/sys/procctl.rs
@@ -0,0 +1,58 @@
//! procctl provides programmatic control over processes.
//!
//! Here we act on the current process, so we save a getpid syscall here.
//!
//! For more documentation, please read [procctl(2)](https://man.freebsd.org/cgi/man.cgi?query=procctl&sektion=2)
use crate::errno::Errno;
use crate::sys::signal::Signal;
use crate::Result;

use libc::c_int;
use std::convert::TryFrom;

/// Enable/disable tracing on the current process, allowing debugging and core dump generation.
pub fn set_dumpable(attribute: bool) -> Result<()> {
let mut dumpable = match attribute {
true => libc::PROC_TRACE_CTL_ENABLE,
false => libc::PROC_TRACE_CTL_DISABLE
};

let res = unsafe { libc::procctl(libc::P_PID, 0, libc::PROC_TRACE_CTL, &mut dumpable as *mut c_int as _) };
Errno::result(res).map(drop)
}

/// Get the tracing status of the current process.
pub fn get_dumpable() -> Result<bool> {
let mut dumpable: c_int = 0;

let res = unsafe { libc::procctl(libc::P_PID, 0, libc::PROC_TRACE_STATUS, &mut dumpable as *mut c_int as _) };
match Errno::result(res) {
Ok(_) => Ok(matches!(dumpable, libc::PROC_TRACE_CTL_ENABLE)),
Err(e) => Err(e),
}
}

/// Set the delivery of the `signal` when the parent of the calling process exits.
pub fn set_pdeathsig<T: Into<Option<Signal>>>(signal: T) -> Result<()> {
let mut sig = match signal.into() {
Some(s) => s as c_int,
None => 0,
};

let res = unsafe { libc::procctl(libc::P_PID, 0, libc::PROC_PDEATHSIG_CTL, &mut sig as *mut c_int as _) };
Errno::result(res).map(drop)
}

/// Get the current signal id that will be delivered to the parent process when it's exiting.
pub fn get_pdeathsig() -> Result<Option<Signal>> {
let mut sig: c_int = 0;

let res = unsafe { libc::procctl(libc::P_PID, 0, libc::PROC_PDEATHSIG_STATUS, &mut sig as *mut c_int as _) };
match Errno::result(res) {
Ok(_) => Ok(match sig {
0 => None,
_ => Some(Signal::try_from(sig)?),
}),
Err(e) => Err(e),
}
}
29 changes: 29 additions & 0 deletions test/sys/test_procctl.rs
@@ -0,0 +1,29 @@
#[cfg(target_os = "freebsd")]
#[cfg(feature = "process")]
mod test_prctl {
use nix::sys::proctl;

#[test]
fn test_get_set_dumpable() {
let original = procctl::get_dumpable().unwrap();

prctl::set_dumpable(false).unwrap();
let dumpable = procctl::get_dumpable().unwrap();
assert!(!dumpable);

prctl::set_dumpable(original).unwrap();
}

#[test]
fn test_get_set_pdeathsig() {
use nix::sys::signal::Signal;

let original = procctl::get_pdeathsig().unwrap();

procctl::set_pdeathsig(Signal::SIGUSR1).unwrap();
let sig = procctl::get_pdeathsig().unwrap();
assert_eq!(sig, Some(Signal::SIGUSR1));

procctl::set_pdeathsig(original).unwrap();
}
}