fn deliver_signal()

in reverie-ptrace/src/perf.rs [665:721]


    fn deliver_signal() {
        ret_without_perf!();
        use std::mem::MaybeUninit;
        use std::sync::mpsc::sync_channel;
        let (tx1, rx1) = sync_channel(0); // send TID
        let (tx2, rx2) = sync_channel(0); // start guest spinn

        // SIGSTKFLT defaults to TERM, so if any thread but the traced one
        // receives the signal, the test will fail due to process exit.
        const MARKER_SIGNAL: Signal = Signal::SIGSTKFLT;
        const SPIN_BRANCHES: u64 = 50000; // big enough to "absorb" noise from debug/release
        const SPINS_PER_EVENT: u64 = 10;
        const SAMPLE_PERIOD: u64 = SPINS_PER_EVENT * SPIN_BRANCHES + (SPINS_PER_EVENT / 4);

        fn signal_is_pending() -> bool {
            unsafe {
                let mut mask = MaybeUninit::<libc::sigset_t>::zeroed();
                libc::sigemptyset(mask.as_mut_ptr());
                libc::sigpending(mask.as_mut_ptr());
                libc::sigismember(mask.as_ptr(), MARKER_SIGNAL as _) == 1
            }
        }

        let handle = std::thread::spawn(move || {
            unsafe {
                let mut mask = MaybeUninit::<libc::sigset_t>::zeroed();
                libc::sigemptyset(mask.as_mut_ptr());
                libc::sigaddset(mask.as_mut_ptr(), MARKER_SIGNAL as _);
                libc::sigprocmask(libc::SIG_BLOCK, mask.as_ptr(), std::ptr::null_mut());
            }

            tx1.send(gettid()).unwrap();
            rx2.recv().unwrap();

            let mut count = 0;
            loop {
                count += 1;
                do_branches(SPIN_BRANCHES);
                if signal_is_pending() {
                    break;
                }
            }
            assert_eq!(count, SPINS_PER_EVENT);
        });

        let tid = rx1.recv().unwrap();
        let pc = Builder::new(tid.as_raw(), -1)
            .sample_period(SAMPLE_PERIOD)
            .event(Event::Hardware(HardwareEvent::BranchInstructions))
            .create()
            .unwrap();
        pc.set_signal_delivery(tid.into(), MARKER_SIGNAL).unwrap();
        pc.enable().unwrap();

        tx2.send(()).unwrap(); // tell thread to start
        handle.join().unwrap(); // propagate panics
    }