Eine aufbereitete Darstellung der Quelle

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

Benutzer

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.9 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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik