Как включить в Linux (Android) BSD-совместимый перезапуск системного вызова при ошибке EINTR (с помощью флага SA_RESTART) - PullRequest
0 голосов
/ 09 января 2019

Я хочу попросить ОС автоматически перезапустить все системные вызовы (например, open, read, write и т. Д.) При ошибке EINTR в Linux (Android), как это работает в 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);

Правильно ли мое решение? Могу ли я найти более простое или элегантное решение? Заранее спасибо.

...