fn native_sigaction_impl()

in sgx_signal/src/signal.rs [147:207]


fn native_sigaction_impl<F>(
    signo: SigNum,
    act: &sigaction,
    oldact: &mut sigaction,
    f: Arc<F>,
) -> SysResult<ActionId>
where
    F: Fn(&siginfo_t) + Sync + Send + 'static,
{
    let global = GlobalData::ensure();
    let mut mask = SigSet::new();
    let old_mask = SigSet::new();

    mask.fill();

    // Guards sigaction calls. This is to ensure that signal handlers are not
    // overwritten between the time sigaction gets |oldact| and sets |act|.
    let (exist, action_id) = {
        let _guard = global.signal_action_lock.lock();
        let exist = if let Some(t) = global.signal_manager.get_action(signo) {
            *oldact = t.get_act();
            true
        } else {
            oldact.sa_sigaction = SIG_DFL;
            false
        };

        rsgx_sigprocmask(SIG_SETMASK, &mask.raw(), &mut old_mask.raw());
        let action_id = global.signal_manager.set_action_impl(signo, act, f);
        rsgx_sigprocmask(SIG_SETMASK, &old_mask.raw(), &mut mask.raw());
        (exist, action_id)
    };

    if exist {
        return Ok(action_id);
    }

    let new_act = sigaction {
        sa_sigaction: 0,
        sa_mask: act.sa_mask,
        sa_flags: act.sa_flags,
        sa_restorer: None,
    };
    if (new_act.sa_flags & SA_RESETHAND) != 0 {
        global.signal_manager.set_reset_on_handle(signo);
    }

    let result = unsafe {
        sigaction(
            signo.raw(),
            &new_act,
            oldact as *mut sigaction,
            get_enclave_id(),
        )
    };
    if result == 0 {
        Ok(action_id)
    } else {
        Err(result)
    }
}