如何在Linux(Android)BSD兼容的syscall上启用EINTR错误时重启(使用标志SA_RESTART)

时间:2019-01-09 11:41:33

标签: c linux signals bsd

我想让OS在Linux(Android)中因EINTR错误而自动重启所有系统调用(例如打开,读取,写入等),就像它在BSD中一样。我发现sigaction带有 SA_RESTART 标志。现在,如果我理解正确,我应该为系统中的每个信号处理程序启用标志 SA_RESTART (( SIGKILL SIGSTOP )除外),这是我的解决方案:


    auto EnableBSDStyleSyscallRestartOnEINTR = [](int sig) -> bool {
        int status;
        struct sigaction act;

        status = sigaction(sig, nullptr, &act);
        if (status == -1) {
            LoggerError("error get sigaction for signal: %d", sig);
            return false;
        }

        if (act.sa_flags & SA_RESTART) {
            return true;
        }

        act.sa_flags |= SA_RESTART;
        status = sigaction(sig, &act, nullptr);
        if (status != 0) {
            LoggerError("can't update sigaction for signal: %d", sig);
            return false;
        }
        return true;
    };

    const auto listOfSignals = {
            SIGHUP,
            SIGINT,
            SIGQUIT,
            SIGILL,
            SIGTRAP,
            SIGABRT,
            SIGIOT,
            SIGBUS,
            SIGFPE,
            // SIGKILL - do not use with sigaction http://man7.org/linux/man-pages/man2/sigaction.2.html
            // SIGUSR1
            SIGSEGV,
            // SIGUSR2
            SIGPIPE,
            SIGALRM,
            SIGTERM,
            SIGSTKFLT,
            SIGCHLD,
            SIGCONT,
            // SIGSTOP - do not use with sigaction http://man7.org/linux/man-pages/man2/sigaction.2.html
            SIGTSTP,
            SIGTTIN,
            SIGTTOU,
            SIGURG,
            SIGXCPU,
            SIGXFSZ,
            SIGVTALRM,
            SIGPROF,
            SIGWINCH,
            SIGIO,
            SIGPWR,
            SIGSYS,
            SIGSWI
    };
    bool all_good = true;
    for (int sig : listOfSignals) {
        all_good &= EnableBSDStyleSyscallRestartOnEINTR(sig);
    }
    assert(all_good);

我的解决方案正确吗?我是更简单或更优雅的解决方案吗?预先感谢。

0 个答案:

没有答案