qemu/linux-user/signal.c
/* do_sigaction() return target values and host errnos */
do_sigaction() return target values and host errnos
do_sigaction () return target values and host errnos
int do_sigaction(int sig, const struct target_sigaction *act,
                 struct target_sigaction *oact)
{
    struct target_sigaction *k;
    struct sigaction act1;
    int host_sig;
    int ret = 0;
    if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) {
        return -TARGET_EINVAL;
    }
    if (block_signals()) {
        return -TARGET_ERESTARTSYS;
    }
    k = &sigact_table[sig - 1];
    if (oact) {
        __put_user(k->_sa_handler, &oact->_sa_handler);
        __put_user(k->sa_flags, &oact->sa_flags);
#ifdef TARGET_ARCH_HAS_SA_RESTORER
        __put_user(k->sa_restorer, &oact->sa_restorer);
#endif
        oact->sa_mask = k->sa_mask;
    }
    if (act) {
        __get_user(k->_sa_handler, &act->_sa_handler);
        __get_user(k->sa_flags, &act->sa_flags);
#ifdef TARGET_ARCH_HAS_SA_RESTORER
        __get_user(k->sa_restorer, &act->sa_restorer);
#endif
        k->sa_mask = act->sa_mask;
        host_sig = target_to_host_signal(sig);
        if (host_sig != SIGSEGV && host_sig != SIGBUS) {
            sigfillset(&act1.sa_mask);
            act1.sa_flags = SA_SIGINFO;
            if (k->sa_flags & TARGET_SA_RESTART)
                act1.sa_flags |= SA_RESTART;
            if (k->_sa_handler == TARGET_SIG_IGN) {
                act1.sa_sigaction = (void *)SIG_IGN;
            } else if (k->_sa_handler == TARGET_SIG_DFL) {
                if (fatal_signal (sig))
                    act1.sa_sigaction = host_signal_handler;
                else
                    act1.sa_sigaction = (void *)SIG_DFL;
            } else {
                act1.sa_sigaction = host_signal_handler;
            }
            ret = sigaction(host_sig, &act1, NULL);
        }
    }
    return ret;
}
int do_sigaction ( int sig , const struct target_sigaction * act , struct target_sigaction * oact ) { struct target_sigaction * k ; struct sigaction act1 ; int host_sig ; int ret = 0 ; if ( sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP ) { return - TARGET_EINVAL ; } if ( block_signals ( ) ) { return - TARGET_ERESTARTSYS ; } k = & sigact_table [ sig - 1 ] ; if ( oact ) { __put_user ( k -> _sa_handler , & oact -> _sa_handler ) ; __put_user ( k -> sa_flags , & oact -> sa_flags ) ; #ifdef TARGET_ARCH_HAS_SA_RESTORER __put_user ( k -> sa_restorer , & oact -> sa_restorer ) ; #endif oact -> sa_mask = k -> sa_mask ; } if ( act ) { __get_user ( k -> _sa_handler , & act -> _sa_handler ) ; __get_user ( k -> sa_flags , & act -> sa_flags ) ; #ifdef TARGET_ARCH_HAS_SA_RESTORER __get_user ( k -> sa_restorer , & act -> sa_restorer ) ; #endif k -> sa_mask = act -> sa_mask ; host_sig = target_to_host_signal ( sig ) ; if ( host_sig != SIGSEGV && host_sig != SIGBUS ) { sigfillset ( & act1 . sa_mask ) ; act1 . sa_flags = SA_SIGINFO ; if ( k -> sa_flags & TARGET_SA_RESTART ) act1 . sa_flags |= SA_RESTART ; if ( k -> _sa_handler == TARGET_SIG_IGN ) { act1 . sa_sigaction = ( void * ) SIG_IGN ; } else if ( k -> _sa_handler == TARGET_SIG_DFL ) { if ( fatal_signal ( sig ) ) act1 . sa_sigaction = host_signal_handler ; else act1 . sa_sigaction = ( void * ) SIG_DFL ; } else { act1 . sa_sigaction = host_signal_handler ; } ret = sigaction ( host_sig , & act1 , NULL ) ; } } return ret ; }
do_sigaction() return target values and host errnos
do_sigaction () return target values and host errnos
/* Not swapped.  */ /* FIXME: This is not threadsafe.  */ /* To be swapped in target_to_host_sigset.  */ /* we update the host linux signal state */ /* NOTE: it is important to update the host kernel signal
               ignore state to avoid getting unexpected interrupted
               syscalls */