Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/nix/test/sys/   (Firefox Browser Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 7 kB image not shown  

Quelle  test_wait.rs

  Sprache: Rust
 

use libc::_exit;
use nix::errno::Errno;
use nix::sys::signal::*;
use nix::sys::wait::*;
use nix::unistd::ForkResult::*;
use nix::unistd::*;

#[test]
#[cfg(not(any(target_os = "redox", target_os = "haiku")))]
fn test_wait_signal() {
    let _m = crate::FORK_MTX.lock();

    // Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe.
    match unsafe { fork() }.expect("Error: Fork Failed") {
        Child => {
            pause();
            unsafe { _exit(123) }
        }
        Parent { child } => {
            kill(child, Some(SIGKILL)).expect("Error: Kill Failed");
            assert_eq!(
                waitpid(child, None),
                Ok(WaitStatus::Signaled(child, SIGKILL, false))
            );
        }
    }
}

#[test]
#[cfg(any(
    target_os = "android",
    target_os = "freebsd",
    //target_os = "haiku",
    all(target_os = "linux", not(target_env = "uclibc")),
))]
#[cfg(not(any(
    target_arch = "mips",
    target_arch = "mips32r6",
    target_arch = "mips64",
    target_arch = "mips64r6"
)))]
fn test_waitid_signal() {
    let _m = crate::FORK_MTX.lock();

    // Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe.
    match unsafe { fork() }.expect("Error: Fork Failed") {
        Child => {
            pause();
            unsafe { _exit(123) }
        }
        Parent { child } => {
            kill(child, Some(SIGKILL)).expect("Error: Kill Failed");
            assert_eq!(
                waitid(Id::Pid(child), WaitPidFlag::WEXITED),
                Ok(WaitStatus::Signaled(child, SIGKILL, false)),
            );
        }
    }
}

#[test]
fn test_wait_exit() {
    let _m = crate::FORK_MTX.lock();

    // Safe: Child only calls `_exit`, which is async-signal-safe.
    match unsafe { fork() }.expect("Error: Fork Failed") {
        Child => unsafe {
            _exit(12);
        },
        Parent { child } => {
            assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 12)));
        }
    }
}

#[cfg(not(target_os = "haiku"))]
#[test]
#[cfg(any(
    target_os = "android",
    target_os = "freebsd",
    target_os = "haiku",
    all(target_os = "linux", not(target_env = "uclibc")),
))]
#[cfg(not(any(
    target_arch = "mips",
    target_arch = "mips32r6",
    target_arch = "mips64",
    target_arch = "mips64r6"
)))]
fn test_waitid_exit() {
    let _m = crate::FORK_MTX.lock();

    // Safe: Child only calls `_exit`, which is async-signal-safe.
    match unsafe { fork() }.expect("Error: Fork Failed") {
        Child => unsafe {
            _exit(12);
        },
        Parent { child } => {
            assert_eq!(
                waitid(Id::Pid(child), WaitPidFlag::WEXITED),
                Ok(WaitStatus::Exited(child, 12)),
            );
        }
    }
}

#[test]
fn test_waitstatus_from_raw() {
    let pid = Pid::from_raw(1);
    assert_eq!(
        WaitStatus::from_raw(pid, 0x0002),
        Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false))
    );
    assert_eq!(
        WaitStatus::from_raw(pid, 0x0200),
        Ok(WaitStatus::Exited(pid, 2))
    );
    assert_eq!(WaitStatus::from_raw(pid, 0x7f7f), Err(Errno::EINVAL));
}

#[test]
fn test_waitstatus_pid() {
    let _m = crate::FORK_MTX.lock();

    match unsafe { fork() }.unwrap() {
        Child => unsafe { _exit(0) },
        Parent { child } => {
            let status = waitpid(child, None).unwrap();
            assert_eq!(status.pid(), Some(child));
        }
    }
}

#[test]
#[cfg(any(
    target_os = "android",
    target_os = "freebsd",
    target_os = "haiku",
    all(target_os = "linux", not(target_env = "uclibc")),
))]
fn test_waitid_pid() {
    let _m = crate::FORK_MTX.lock();

    match unsafe { fork() }.unwrap() {
        Child => unsafe { _exit(0) },
        Parent { child } => {
            let status = waitid(Id::Pid(child), WaitPidFlag::WEXITED).unwrap();
            assert_eq!(status.pid(), Some(child));
        }
    }
}

#[cfg(linux_android)]
// FIXME: qemu-user doesn't implement ptrace on most arches
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod ptrace {
    use crate::*;
    use libc::_exit;
    use nix::sys::ptrace::{self, Event, Options};
    use nix::sys::signal::*;
    use nix::sys::wait::*;
    use nix::unistd::ForkResult::*;
    use nix::unistd::*;

    fn ptrace_child() -> ! {
        ptrace::traceme().unwrap();
        // As recommended by ptrace(2), raise SIGTRAP to pause the child
        // until the parent is ready to continue
        raise(SIGTRAP).unwrap();
        unsafe { _exit(0) }
    }

    fn ptrace_wait_parent(child: Pid) {
        // Wait for the raised SIGTRAP
        assert_eq!(
            waitpid(child, None),
            Ok(WaitStatus::Stopped(child, SIGTRAP))
        );
        // We want to test a syscall stop and a PTRACE_EVENT stop
        ptrace::setoptions(
            child,
            Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT,
        )
        .expect("setoptions failed");

        // First, stop on the next system call, which will be exit()
        ptrace::syscall(child, None).expect("syscall failed");
        assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
        // Then get the ptrace event for the process exiting
        ptrace::cont(child, None).expect("cont failed");
        assert_eq!(
            waitpid(child, None),
            Ok(WaitStatus::PtraceEvent(
                child,
                SIGTRAP,
                Event::PTRACE_EVENT_EXIT as i32
            ))
        );
        // Finally get the normal wait() result, now that the process has exited
        ptrace::cont(child, None).expect("cont failed");
        assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 0)));
    }

    #[cfg(not(target_env = "uclibc"))]
    fn ptrace_waitid_parent(child: Pid) {
        // Wait for the raised SIGTRAP
        //
        // Unlike waitpid(), waitid() can distinguish trap events from regular
        // stop events, so unlike ptrace_wait_parent(), we get a PtraceEvent here
        assert_eq!(
            waitid(Id::Pid(child), WaitPidFlag::WEXITED),
            Ok(WaitStatus::PtraceEvent(child, SIGTRAP, 0)),
        );
        // We want to test a syscall stop and a PTRACE_EVENT stop
        ptrace::setoptions(
            child,
            Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT,
        )
        .expect("setopts failed");

        // First, stop on the next system call, which will be exit()
        ptrace::syscall(child, None).expect("syscall failed");
        assert_eq!(
            waitid(Id::Pid(child), WaitPidFlag::WEXITED),
            Ok(WaitStatus::PtraceSyscall(child)),
        );
        // Then get the ptrace event for the process exiting
        ptrace::cont(child, None).expect("cont failed");
        assert_eq!(
            waitid(Id::Pid(child), WaitPidFlag::WEXITED),
            Ok(WaitStatus::PtraceEvent(
                child,
                SIGTRAP,
                Event::PTRACE_EVENT_EXIT as i32
            )),
        );
        // Finally get the normal wait() result, now that the process has exited
        ptrace::cont(child, None).expect("cont failed");
        assert_eq!(
            waitid(Id::Pid(child), WaitPidFlag::WEXITED),
            Ok(WaitStatus::Exited(child, 0)),
        );
    }

    #[test]
    fn test_wait_ptrace() {
        require_capability!("test_wait_ptrace", CAP_SYS_PTRACE);
        let _m = crate::FORK_MTX.lock();

        match unsafe { fork() }.expect("Error: Fork Failed") {
            Child => ptrace_child(),
            Parent { child } => ptrace_wait_parent(child),
        }
    }

    #[test]
    #[cfg(not(target_env = "uclibc"))]
    fn test_waitid_ptrace() {
        require_capability!("test_waitid_ptrace", CAP_SYS_PTRACE);
        let _m = crate::FORK_MTX.lock();

        match unsafe { fork() }.expect("Error: Fork Failed") {
            Child => ptrace_child(),
            Parent { child } => ptrace_waitid_parent(child),
        }
    }
}

Messung V0.5 in Prozent
C=80 H=94 G=87

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-06-19) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.