Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  test_wait.rs   Sprache: unbekannt

 
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),
        }
    }
}

[ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge