summaryrefslogtreecommitdiff
path: root/test/sys
diff options
context:
space:
mode:
authorxd009642 <danielmckenna93@gmail.com>2018-10-06 15:31:33 +0100
committerxd009642 <danielmckenna93@gmail.com>2018-10-21 18:17:48 +0100
commitf1573a7efa8368507d581adeb3bff9bbf5aa0ead (patch)
tree588c18b2f92397d9593ef1726ad7b6b2514952a4 /test/sys
parenteef3a432d57e8f830e05fede6e3099dcb689aa6b (diff)
downloadnix-f1573a7efa8368507d581adeb3bff9bbf5aa0ead.zip
Added ptrace support for BSDs
* Moved ptrace API into it's own module with cfg'ed modules exported for linux/android or BSDs. * Replicated current linux API for BSD * Added API functions to peek and poke memory to avoid needing to replicate deprecated linux API and remaining feature complete * Added helper function for `PTRACE_KILL` requests * Updated tests based on new API changes * Added addition kill calls to `test_ptrace_cont` as inferior death doesn't happen immediately on OSX which caused issues in the tests.
Diffstat (limited to 'test/sys')
-rw-r--r--test/sys/mod.rs7
-rw-r--r--test/sys/test_ptrace.rs28
2 files changed, 29 insertions, 6 deletions
diff --git a/test/sys/mod.rs b/test/sys/mod.rs
index bdc079d8..46f29123 100644
--- a/test/sys/mod.rs
+++ b/test/sys/mod.rs
@@ -27,5 +27,10 @@ mod test_uio;
mod test_epoll;
mod test_pthread;
#[cfg(any(target_os = "android",
- target_os = "linux"))]
+ target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "linux",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "openbsd"))]
mod test_ptrace;
diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs
index a15a7921..24d9b522 100644
--- a/test/sys/test_ptrace.rs
+++ b/test/sys/test_ptrace.rs
@@ -1,7 +1,9 @@
use nix::Error;
use nix::errno::Errno;
use nix::unistd::getpid;
-use nix::sys::ptrace::{self, Options};
+use nix::sys::ptrace;
+#[cfg(any(target_os = "android", target_os = "linux"))]
+use nix::sys::ptrace::Options;
#[cfg(any(target_os = "android", target_os = "linux"))]
use std::mem;
@@ -11,11 +13,13 @@ fn test_ptrace() {
// Just make sure ptrace can be called at all, for now.
// FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS
let err = ptrace::attach(getpid()).unwrap_err();
- assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::ENOSYS));
+ assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::EINVAL) ||
+ err == Error::Sys(Errno::ENOSYS));
}
// Just make sure ptrace_setoptions can be called at all, for now.
#[test]
+#[cfg(any(target_os = "android", target_os = "linux"))]
fn test_ptrace_setoptions() {
let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD).unwrap_err();
assert!(err != Error::UnsupportedOperation);
@@ -23,6 +27,7 @@ fn test_ptrace_setoptions() {
// Just make sure ptrace_getevent can be called at all, for now.
#[test]
+#[cfg(any(target_os = "android", target_os = "linux"))]
fn test_ptrace_getevent() {
let err = ptrace::getevent(getpid()).unwrap_err();
assert!(err != Error::UnsupportedOperation);
@@ -30,6 +35,7 @@ fn test_ptrace_getevent() {
// Just make sure ptrace_getsiginfo can be called at all, for now.
#[test]
+#[cfg(any(target_os = "android", target_os = "linux"))]
fn test_ptrace_getsiginfo() {
if let Err(Error::UnsupportedOperation) = ptrace::getsiginfo(getpid()) {
panic!("ptrace_getsiginfo returns Error::UnsupportedOperation!");
@@ -38,6 +44,7 @@ fn test_ptrace_getsiginfo() {
// Just make sure ptrace_setsiginfo can be called at all, for now.
#[test]
+#[cfg(any(target_os = "android", target_os = "linux"))]
fn test_ptrace_setsiginfo() {
let siginfo = unsafe { mem::uninitialized() };
if let Err(Error::UnsupportedOperation) = ptrace::setsiginfo(getpid(), &siginfo) {
@@ -50,10 +57,12 @@ fn test_ptrace_setsiginfo() {
fn test_ptrace_cont() {
use nix::sys::ptrace;
use nix::sys::signal::{raise, Signal};
- use nix::sys::wait::{waitpid, WaitStatus};
+ use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
use nix::unistd::fork;
use nix::unistd::ForkResult::*;
+ let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+
// FIXME: qemu-user doesn't implement ptrace on all architectures
// and retunrs ENOSYS in this case.
// We (ab)use this behavior to detect the affected platforms
@@ -79,9 +88,18 @@ fn test_ptrace_cont() {
assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP)));
ptrace::cont(child, None).unwrap();
assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP)));
- ptrace::cont(child, Signal::SIGKILL).unwrap();
+ ptrace::cont(child, Some(Signal::SIGKILL)).unwrap();
match waitpid(child, None) {
- Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {}
+ Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {
+ // FIXME It's been observed on some systems (apple) the
+ // tracee may not be killed but remain as a zombie process
+ // affecting other wait based tests. Add an extra kill just
+ // to make sure there are no zombies.
+ let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
+ while ptrace::cont(child, Some(Signal::SIGKILL)).is_ok() {
+ let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
+ }
+ }
_ => panic!("The process should have been killed"),
}
},