LINUX.ORG.RU

обработать сигнал sigchld при прерывании функции poll

 , ,


0

1

здравствуйте, есть код следующего вида:

//обработчик сигналов
void sig_usr(int signo) 
{
    if (signo == SIGKILL)
        printf("signal SIGKILL\n");
    else if (signo == SIGCHLD)
        printf("signal SIGCHLD\n");
    else
        printf("signal %d\n", signo);
}

int main(int argc, char**argv) {
    //устанавливаем обработчик
    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = sig_usr;
    sigset_t   set;
    sigemptyset(&set);
    sigaddset(&set, SIGKILL);
    sigaddset(&set, SIGCHLD);
    act.sa_mask = set;
    sigaction(SIGKILL, &act, 0);
    sigaction(SIGCHLD, &act, 0);

    while(true) {
        retval = ::poll(clients, max + 1, -1);
        if(errno == EINTR) {
            std::cout << "interrupt syscall  and reload poll\n";
            continue;
        }
       /*много всего*/
    }
}
когда выполненине блокируется на poll и если кидаем sigchld, то вызывается обработчик и errno становится EINTR(судя по выводу) и дальше выполнение снова блокируется на poll. Вроде бы все нормально, ждем входящих соединений... Однако если далее подключиться клиентом, то бесконечно начинается крутиться цикл до первого continue(который внутри if) и, как я понимаю, на poll уже не блокируется выполнение. Объясните почему так и как это преодолеть. Да и sigkill, если честно, не отлавливается версия ядра 4.11.0

★★

Последнее исправление: xperious (всего исправлений: 1)

Объясните почему так

Потому что errno устанавливается только когда какая-нибудь функция возвращает ошибку (-1). Если функция завершается успешно, она не трогает errno. В нём остаётся лежать старое значение.

и как это преодолеть

Проверяй retval:

if (retval == -1 && errno == EINTR) {

Всегда проверяй.

i-rinat ★★★★★
()

Да и sigkill, если честно, не отлавливается версия ядра 4.11.0

Предлагаю почитать документацию, man signal:

The signals SIGKILL and SIGSTOP cannot be caught or ignored.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Потому что errno устанавливается только когда какая-нибудь функция возвращает ошибку (-1). Если функция завершается успешно, она не трогает errno.

хм, errno меняется ядром когда какой-нибудь системный вызов возвращает -1?

Предлагаю почитать документацию, man signal:

да я по книжкам... в итоге невнимательно

xperious ★★
() автор топика
Ответ на: комментарий от xperious

хм, errno меняется ядром когда какой-нибудь системный вызов возвращает -1?

Нет, errno — это переменная внутри libc, её устанавливают функции из libc. Ядро не лезет в память пользовательского процесса. Да и как оно определит, где errno находится?

Ты не делаешь системные вызовы напрямую, вместо этого твой код вызывает функции из libc. Они уже делают необходимые приготовления, затем делают системный вызов, затем обрабатывают ответ.

Например, системный вызов read может вернуть -EBADF, если ты ему передашь некорректный файловый дескриптор. А функция read() из libc, которая и делает внутри себя системный вызов read, в этом случае вернёт тебе -1, а в errno положит EBADF.

i-rinat ★★★★★
()
Ответ на: комментарий от xperious

какой-нибудь системный вызов возвращает -1

Не -1 а «ошибку». Минимум в одной версии был минимум один вызов, который возвращал что-то очень похожее на -1 при успешном завершении.

DonkeyHot ★★★★★
()
Ответ на: комментарий от xperious

ну давай договоримся, что суть юникса 1980х есть говно. тебе что, реально надо страдать как в 1980х? не страдай, уже 2010е?, можно ждать как сигнала так и событий на fd(исключение - файлы, там какой то анал дикий).

ckotinko ☆☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.