summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md17
-rw-r--r--Cargo.toml2
-rw-r--r--src/macros.rs128
-rw-r--r--src/sys/event.rs25
-rw-r--r--src/sys/ptrace/linux.rs18
-rw-r--r--src/sys/signal.rs77
-rw-r--r--src/sys/termios.rs121
-rw-r--r--test/sys/test_ptrace.rs42
8 files changed, 271 insertions, 159 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5031d02c..3e2c9680 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
(#[1473](https://github.com/nix-rust/nix/pull/1473))
- Added `setrlimit` and `getrlimit`.
(#[1302](https://github.com/nix-rust/nix/pull/1302))
+- Added `ptrace::interrupt` method for platforms that support `PTRACE_INTERRUPT`
+ (#[1422](https://github.com/nix-rust/nix/pull/1422))
### Changed
@@ -43,14 +45,29 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Many more functions, mostly contructors, are now `const`.
(#[1476](https://github.com/nix-rust/nix/pull/1476))
+- `sys::event::KEvent::filter` now returns a `Result` instead of being
+ infalliable. The only cases where it will now return an error are cases
+ where it previously would've had undefined behavior.
+ (#[1484](https://github.com/nix-rust/nix/pull/1484))
+
### Fixed
- Added more errno definitions for better backwards compatibility with
Nix 0.21.0.
(#[1467](https://github.com/nix-rust/nix/pull/1467))
+- Fixed potential undefined behavior in `Signal::try_from` on some platforms.
+ (#[1484](https://github.com/nix-rust/nix/pull/1484))
+
### Removed
+- Removed a couple of termios constants on redox that were never actually
+ supported.
+ (#[1483](https://github.com/nix-rust/nix/pull/1483))
+- Removed `nix::sys::signal::NSIG`. It was of dubious utility, and not correct
+ for all platforms.
+ (#[1484](https://github.com/nix-rust/nix/pull/1484))
+
## [0.22.0] - 9 July 2021
### Added
- Added `if_nameindex` (#[1445](https://github.com/nix-rust/nix/pull/1445))
diff --git a/Cargo.toml b/Cargo.toml
index 5f5daf16..dc565aee 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,7 +25,7 @@ targets = [
]
[dependencies]
-libc = { git = "https://github.com/rust-lang/libc", rev = "9c1489fa8", features = [ "extra_traits" ] }
+libc = { git = "https://github.com/rust-lang/libc", rev = "f5e31f208", features = [ "extra_traits" ] }
bitflags = "1.1"
cfg-if = "1.0"
diff --git a/src/macros.rs b/src/macros.rs
index 7d6ac8df..927e7e7c 100644
--- a/src/macros.rs
+++ b/src/macros.rs
@@ -83,9 +83,9 @@ macro_rules! libc_bitflags {
macro_rules! libc_enum {
// Exit rule.
(@make_enum
+ name: $BitFlags:ident,
{
$v:vis
- name: $BitFlags:ident,
attrs: [$($attrs:tt)*],
entries: [$($entries:tt)*],
}
@@ -97,38 +97,98 @@ macro_rules! libc_enum {
}
};
+ // Exit rule including TryFrom
+ (@make_enum
+ name: $BitFlags:ident,
+ {
+ $v:vis
+ attrs: [$($attrs:tt)*],
+ entries: [$($entries:tt)*],
+ from_type: $repr:path,
+ try_froms: [$($try_froms:tt)*]
+ }
+ ) => {
+ $($attrs)*
+ #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+ $v enum $BitFlags {
+ $($entries)*
+ }
+ #[allow(unused_doc_comment)]
+ impl ::std::convert::TryFrom<$repr> for $BitFlags {
+ type Error = $crate::Error;
+ fn try_from(x: $repr) -> $crate::Result<Self> {
+ match x {
+ $($try_froms)*
+ _ => Err($crate::Error::EINVAL)
+ }
+ }
+ }
+ };
+
// Done accumulating.
(@accumulate_entries
+ name: $BitFlags:ident,
+ {
+ $v:vis
+ attrs: $attrs:tt,
+ },
+ $entries:tt,
+ $try_froms:tt;
+ ) => {
+ libc_enum! {
+ @make_enum
+ name: $BitFlags,
+ {
+ $v
+ attrs: $attrs,
+ entries: $entries,
+ }
+ }
+ };
+
+ // Done accumulating and want TryFrom
+ (@accumulate_entries
+ name: $BitFlags:ident,
{
$v:vis
- name: $BitFlags:ident,
attrs: $attrs:tt,
+ from_type: $repr:path,
},
- $entries:tt;
+ $entries:tt,
+ $try_froms:tt;
) => {
libc_enum! {
@make_enum
+ name: $BitFlags,
{
$v
- name: $BitFlags,
attrs: $attrs,
entries: $entries,
+ from_type: $repr,
+ try_froms: $try_froms
}
}
};
// Munch an attr.
(@accumulate_entries
+ name: $BitFlags:ident,
$prefix:tt,
- [$($entries:tt)*];
+ [$($entries:tt)*],
+ [$($try_froms:tt)*];
#[$attr:meta] $($tail:tt)*
) => {
libc_enum! {
@accumulate_entries
+ name: $BitFlags,
$prefix,
[
$($entries)*
#[$attr]
+ ],
+ [
+ $($try_froms)*
+ #[$attr]
];
$($tail)*
}
@@ -136,32 +196,47 @@ macro_rules! libc_enum {
// Munch last ident if not followed by a comma.
(@accumulate_entries
+ name: $BitFlags:ident,
$prefix:tt,
- [$($entries:tt)*];
+ [$($entries:tt)*],
+ [$($try_froms:tt)*];
$entry:ident
) => {
libc_enum! {
@accumulate_entries
+ name: $BitFlags,
$prefix,
[
$($entries)*
$entry = libc::$entry,
+ ],
+ [
+ $($try_froms)*
+ libc::$entry => Ok($BitFlags::$entry),
];
}
};
// Munch an ident; covers terminating comma case.
(@accumulate_entries
+ name: $BitFlags:ident,
$prefix:tt,
- [$($entries:tt)*];
- $entry:ident, $($tail:tt)*
+ [$($entries:tt)*],
+ [$($try_froms:tt)*];
+ $entry:ident,
+ $($tail:tt)*
) => {
libc_enum! {
@accumulate_entries
+ name: $BitFlags,
$prefix,
[
$($entries)*
$entry = libc::$entry,
+ ],
+ [
+ $($try_froms)*
+ libc::$entry => Ok($BitFlags::$entry),
];
$($tail)*
}
@@ -169,16 +244,24 @@ macro_rules! libc_enum {
// Munch an ident and cast it to the given type; covers terminating comma.
(@accumulate_entries
+ name: $BitFlags:ident,
$prefix:tt,
- [$($entries:tt)*];
- $entry:ident as $ty:ty, $($tail:tt)*
+ [$($entries:tt)*],
+ [$($try_froms:tt)*];
+ $entry:ident as $ty:ty,
+ $($tail:tt)*
) => {
libc_enum! {
@accumulate_entries
+ name: $BitFlags,
$prefix,
[
$($entries)*
$entry = libc::$entry as $ty,
+ ],
+ [
+ $($try_froms)*
+ libc::$entry as $ty => Ok($BitFlags::$entry),
];
$($tail)*
}
@@ -193,11 +276,34 @@ macro_rules! libc_enum {
) => {
libc_enum! {
@accumulate_entries
+ name: $BitFlags,
+ {
+ $v
+ attrs: [$(#[$attr])*],
+ },
+ [],
+ [];
+ $($vals)*
+ }
+ };
+
+ // Entry rule including TryFrom
+ (
+ $(#[$attr:meta])*
+ $v:vis enum $BitFlags:ident {
+ $($vals:tt)*
+ }
+ impl TryFrom<$repr:path>
+ ) => {
+ libc_enum! {
+ @accumulate_entries
+ name: $BitFlags,
{
$v
- name: $BitFlags,
attrs: [$(#[$attr])*],
+ from_type: $repr,
},
+ [],
[];
$($vals)*
}
diff --git a/src/sys/event.rs b/src/sys/event.rs
index 1f4c1b41..c648f5eb 100644
--- a/src/sys/event.rs
+++ b/src/sys/event.rs
@@ -6,9 +6,9 @@ use crate::{Errno, Result};
use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
#[cfg(target_os = "netbsd")]
use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
+use std::convert::TryInto;
use std::os::unix::io::RawFd;
use std::ptr;
-use std::mem;
// Redefine kevent in terms of programmer-friendly enums and bitfields.
#[repr(C)]
@@ -76,6 +76,7 @@ libc_enum! {
EVFILT_VNODE,
EVFILT_WRITE,
}
+ impl TryFrom<type_of_event_filter>
}
#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
@@ -233,8 +234,8 @@ impl KEvent {
self.kevent.ident
}
- pub fn filter(&self) -> EventFilter {
- unsafe { mem::transmute(self.kevent.filter as type_of_event_filter) }
+ pub fn filter(&self) -> Result<EventFilter> {
+ self.kevent.filter.try_into()
}
pub fn flags(&self) -> EventFlag {
@@ -313,6 +314,8 @@ pub fn ev_set(ev: &mut KEvent,
#[test]
fn test_struct_kevent() {
+ use std::mem;
+
let udata : intptr_t = 12345;
let actual = KEvent::new(0xdead_beef,
@@ -322,10 +325,24 @@ fn test_struct_kevent() {
0x1337,
udata);
assert_eq!(0xdead_beef, actual.ident());
- assert_eq!(libc::EVFILT_READ, actual.filter() as type_of_event_filter);
+ let filter = actual.kevent.filter;
+ assert_eq!(libc::EVFILT_READ, filter);
assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits());
assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits());
assert_eq!(0x1337, actual.data() as type_of_data);
assert_eq!(udata as type_of_udata, actual.udata() as type_of_udata);
assert_eq!(mem::size_of::<libc::kevent>(), mem::size_of::<KEvent>());
}
+
+#[test]
+fn test_kevent_filter() {
+ let udata : intptr_t = 12345;
+
+ let actual = KEvent::new(0xdead_beef,
+ EventFilter::EVFILT_READ,
+ EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
+ FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
+ 0x1337,
+ udata);
+ assert_eq!(EventFilter::EVFILT_READ, actual.filter().unwrap());
+}
diff --git a/src/sys/ptrace/linux.rs b/src/sys/ptrace/linux.rs
index 74a23e03..ef1dafbb 100644
--- a/src/sys/ptrace/linux.rs
+++ b/src/sys/ptrace/linux.rs
@@ -98,11 +98,9 @@ libc_enum!{
#[cfg(all(target_os = "linux", not(any(target_arch = "mips",
target_arch = "mips64"))))]
PTRACE_SETREGSET,
- #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
+ #[cfg(target_os = "linux")]
PTRACE_SEIZE,
- #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
- target_arch = "mips64"))))]
+ #[cfg(target_os = "linux")]
PTRACE_INTERRUPT,
#[cfg(all(target_os = "linux", not(any(target_arch = "mips",
target_arch = "mips64"))))]
@@ -339,7 +337,7 @@ pub fn attach(pid: Pid) -> Result<()> {
/// Attach to a running process, as with `ptrace(PTRACE_SEIZE, ...)`
///
/// Attaches to the process specified in pid, making it a tracee of the calling process.
-#[cfg(all(target_os = "linux", not(any(target_arch = "mips", target_arch = "mips64"))))]
+#[cfg(target_os = "linux")]
pub fn seize(pid: Pid, options: Options) -> Result<()> {
unsafe {
ptrace_other(
@@ -384,6 +382,16 @@ pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
}
}
+/// Stop a tracee, as with `ptrace(PTRACE_INTERRUPT, ...)`
+///
+/// This request is equivalent to `ptrace(PTRACE_INTERRUPT, ...)`
+#[cfg(target_os = "linux")]
+pub fn interrupt(pid: Pid) -> Result<()> {
+ unsafe {
+ ptrace_other(Request::PTRACE_INTERRUPT, pid, ptr::null_mut(), ptr::null_mut()).map(drop)
+ }
+}
+
/// Issues a kill request as with `ptrace(PTRACE_KILL, ...)`
///
/// This request is equivalent to `ptrace(PTRACE_CONT, ..., SIGKILL);`
diff --git a/src/sys/signal.rs b/src/sys/signal.rs
index 0911cfaa..e68ebf16 100644
--- a/src/sys/signal.rs
+++ b/src/sys/signal.rs
@@ -6,7 +6,6 @@
use crate::{Error, Result};
use crate::errno::Errno;
use crate::unistd::Pid;
-use std::convert::TryFrom;
use std::mem;
use std::fmt;
use std::str::FromStr;
@@ -71,6 +70,7 @@ libc_enum!{
target_os = "redox")))]
SIGINFO,
}
+ impl TryFrom<i32>
}
impl FromStr for Signal {
@@ -335,8 +335,6 @@ const SIGNALS: [Signal; 31] = [
SIGEMT,
SIGINFO];
-pub const NSIG: libc::c_int = 32;
-
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct SignalIterator {
next: usize,
@@ -362,18 +360,6 @@ impl Signal {
}
}
-impl TryFrom<libc::c_int> for Signal {
- type Error = Error;
-
- fn try_from(signum: libc::c_int) -> Result<Signal> {
- if 0 < signum && signum < NSIG {
- Ok(unsafe { mem::transmute(signum) })
- } else {
- Err(Error::from(Errno::EINVAL))
- }
- }
-}
-
pub const SIGIOT : Signal = SIGABRT;
pub const SIGPOLL : Signal = SIGIO;
pub const SIGUNUSED : Signal = SIGSYS;
@@ -489,6 +475,8 @@ impl SigSet {
/// signal mask becomes pending, and returns the accepted signal.
#[cfg(not(target_os = "redox"))] // RedoxFS does not yet support sigwait
pub fn wait(&self) -> Result<Signal> {
+ use std::convert::TryFrom;
+
let mut signum = mem::MaybeUninit::uninit();
let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) };
@@ -584,9 +572,31 @@ impl SigAction {
match self.sigaction.sa_sigaction {
libc::SIG_DFL => SigHandler::SigDfl,
libc::SIG_IGN => SigHandler::SigIgn,
- f if self.flags().contains(SaFlags::SA_SIGINFO) =>
- SigHandler::SigAction( unsafe { mem::transmute(f) } ),
- f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
+ p if self.flags().contains(SaFlags::SA_SIGINFO) =>
+ SigHandler::SigAction(
+ // Safe for one of two reasons:
+ // * The SigHandler was created by SigHandler::new, in which
+ // case the pointer is correct, or
+ // * The SigHandler was created by signal or sigaction, which
+ // are unsafe functions, so the caller should've somehow
+ // ensured that it is correctly initialized.
+ unsafe{
+ *(&p as *const usize
+ as *const extern fn(_, _, _))
+ }
+ as extern fn(_, _, _)),
+ p => SigHandler::Handler(
+ // Safe for one of two reasons:
+ // * The SigHandler was created by SigHandler::new, in which
+ // case the pointer is correct, or
+ // * The SigHandler was created by signal or sigaction, which
+ // are unsafe functions, so the caller should've somehow
+ // ensured that it is correctly initialized.
+ unsafe{
+ *(&p as *const usize
+ as *const extern fn(libc::c_int))
+ }
+ as extern fn(libc::c_int)),
}
}
@@ -596,7 +606,18 @@ impl SigAction {
match self.sigaction.sa_handler {
libc::SIG_DFL => SigHandler::SigDfl,
libc::SIG_IGN => SigHandler::SigIgn,
- f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
+ p => SigHandler::Handler(
+ // Safe for one of two reasons:
+ // * The SigHandler was created by SigHandler::new, in which
+ // case the pointer is correct, or
+ // * The SigHandler was created by signal or sigaction, which
+ // are unsafe functions, so the caller should've somehow
+ // ensured that it is correctly initialized.
+ unsafe{
+ *(&p as *const usize
+ as *const extern fn(libc::c_int))
+ }
+ as extern fn(libc::c_int)),
}
}
}
@@ -608,9 +629,16 @@ impl SigAction {
///
/// # Safety
///
-/// Signal handlers may be called at any point during execution, which limits what is safe to do in
-/// the body of the signal-catching function. Be certain to only make syscalls that are explicitly
-/// marked safe for signal handlers and only share global data using atomics.
+/// * Signal handlers may be called at any point during execution, which limits
+/// what is safe to do in the body of the signal-catching function. Be certain
+/// to only make syscalls that are explicitly marked safe for signal handlers
+/// and only share global data using atomics.
+///
+/// * There is also no guarantee that the old signal handler was installed
+/// correctly. If it was installed by this crate, it will be. But if it was
+/// installed by, for example, C code, then there is no guarantee its function
+/// pointer is valid. In that case, this function effectively dereferences a
+/// raw pointer of unknown provenance.
pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
@@ -689,7 +717,10 @@ pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler>
match oldhandler {
libc::SIG_DFL => SigHandler::SigDfl,
libc::SIG_IGN => SigHandler::SigIgn,
- f => SigHandler::Handler(mem::transmute(f)),
+ p => SigHandler::Handler(
+ *(&p as *const usize
+ as *const extern fn(libc::c_int))
+ as extern fn(libc::c_int)),
}
})
}
diff --git a/src/sys/termios.rs b/src/sys/termios.rs
index b29d3b98..01d46080 100644
--- a/src/sys/termios.rs
+++ b/src/sys/termios.rs
@@ -152,11 +152,11 @@
//! # }
//! ```
use cfg_if::cfg_if;
-use crate::{Error, Result};
+use crate::Result;
use crate::errno::Errno;
use libc::{self, c_int, tcflag_t};
use std::cell::{Ref, RefCell};
-use std::convert::{From, TryFrom};
+use std::convert::From;
use std::mem;
use std::os::unix::io::RawFd;
@@ -340,119 +340,7 @@ libc_enum!{
#[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
B4000000,
}
-}
-
-impl TryFrom<libc::speed_t> for BaudRate {
- type Error = Error;
-
- fn try_from(s: libc::speed_t) -> Result<BaudRate> {
- use libc::{B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800,
- B9600, B19200, B38400, B57600, B115200, B230400};
- #[cfg(any(target_os = "android", target_os = "linux"))]
- use libc::{B500000, B576000, B1000000, B1152000, B1500000, B2000000};
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- use libc::{B2500000, B3000000, B3500000, B4000000};
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- use libc::{B7200, B14400, B28800, B76800};
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "linux",
- target_os = "netbsd"))]
- use libc::{B460800, B921600};
- #[cfg(any(target_os = "illumos", target_os = "solaris"))]
- use libc::{B153600, B307200, B460800, B921600};
-
- match s {
- B0 => Ok(BaudRate::B0),
- B50 => Ok(BaudRate::B50),
- B75 => Ok(BaudRate::B75),
- B110 => Ok(BaudRate::B110),
- B134 => Ok(BaudRate::B134),
- B150 => Ok(BaudRate::B150),
- B200 => Ok(BaudRate::B200),
- B300 => Ok(BaudRate::B300),
- B600 => Ok(BaudRate::B600),
- B1200 => Ok(BaudRate::B1200),
- B1800 => Ok(BaudRate::B1800),
- B2400 => Ok(BaudRate::B2400),
- B4800 => Ok(BaudRate::B4800),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B7200 => Ok(BaudRate::B7200),
- B9600 => Ok(BaudRate::B9600),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B14400 => Ok(BaudRate::B14400),
- B19200 => Ok(BaudRate::B19200),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B28800 => Ok(BaudRate::B28800),
- B38400 => Ok(BaudRate::B38400),
- B57600 => Ok(BaudRate::B57600),
- #[cfg(any(target_os = "dragonfly",
- target_os = "freebsd",
- target_os = "macos",
- target_os = "netbsd",
- target_os = "openbsd"))]
- B76800 => Ok(BaudRate::B76800),
- B115200 => Ok(BaudRate::B115200),
- #[cfg(any(target_os = "illumos",
- target_os = "solaris"))]
- B153600 => Ok(BaudRate::B153600),
- B230400 => Ok(BaudRate::B230400),
- #[cfg(any(target_os = "illumos",
- target_os = "solaris"))]
- B307200 => Ok(BaudRate::B307200),
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "solaris"))]
- B460800 => Ok(BaudRate::B460800),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B500000 => Ok(BaudRate::B500000),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B576000 => Ok(BaudRate::B576000),
- #[cfg(any(target_os = "android",
- target_os = "freebsd",
- target_os = "illumos",
- target_os = "linux",
- target_os = "netbsd",
- target_os = "solaris"))]
- B921600 => Ok(BaudRate::B921600),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B1000000 => Ok(BaudRate::B1000000),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B1152000 => Ok(BaudRate::B1152000),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B1500000 => Ok(BaudRate::B1500000),
- #[cfg(any(target_os = "android", target_os = "linux"))]
- B2000000 => Ok(BaudRate::B2000000),
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B2500000 => Ok(BaudRate::B2500000),
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B3000000 => Ok(BaudRate::B3000000),
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B3500000 => Ok(BaudRate::B3500000),
- #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
- B4000000 => Ok(BaudRate::B4000000),
- _ => Err(Error::from(Errno::EINVAL))
- }
- }
+ impl TryFrom<libc::speed_t>
}
#[cfg(any(target_os = "freebsd",
@@ -604,7 +492,9 @@ libc_bitflags! {
ICRNL;
IXON;
IXOFF;
+ #[cfg(not(target_os = "redox"))]
IXANY;
+ #[cfg(not(target_os = "redox"))]
IMAXBEL;
#[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
IUTF8;
@@ -1116,6 +1006,7 @@ pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
#[cfg(test)]
mod test {
use super::*;
+ use std::convert::TryFrom;
#[test]
fn try_from() {
diff --git a/test/sys/test_ptrace.rs b/test/sys/test_ptrace.rs
index 985945d1..ceb39b9b 100644
--- a/test/sys/test_ptrace.rs
+++ b/test/sys/test_ptrace.rs
@@ -114,6 +114,48 @@ fn test_ptrace_cont() {
}
}
+#[cfg(target_os = "linux")]
+#[test]
+fn test_ptrace_interrupt() {
+ use nix::sys::ptrace;
+ use nix::sys::signal::Signal;
+ use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
+ use nix::unistd::fork;
+ use nix::unistd::ForkResult::*;
+ use std::thread::sleep;
+ use std::time::Duration;
+
+ require_capability!(CAP_SYS_PTRACE);
+
+ let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+
+ match unsafe{fork()}.expect("Error: Fork Failed") {
+ Child => {
+ loop {
+ sleep(Duration::from_millis(1000));
+ }
+
+ },
+ Parent { child } => {
+ ptrace::seize(child, ptrace::Options::PTRACE_O_TRACESYSGOOD).unwrap();
+ ptrace::interrupt(child).unwrap();
+ assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceEvent(child, Signal::SIGTRAP, 128)));
+ ptrace::syscall(child, None).unwrap();
+ assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
+ ptrace::detach(child, Some(Signal::SIGKILL)).unwrap();
+ match waitpid(child, None) {
+ Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {
+ 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"),
+ }
+ },
+ }
+}
+
// ptrace::{setoptions, getregs} are only available in these platforms
#[cfg(all(target_os = "linux",
any(target_arch = "x86_64",