2016-01-21 2 views
0

Я пытаюсь лучше понять семафоры и весь этот джаз, и для этого я программирую сервер и клиенты, которые обмениваются данными с использованием разделяемой памяти и семафоров. Он работает очень хорошо и все, но я не уверен, что понимаю, как правильно работает обработка сигналов в этом случае. Это пример кода с моего сервера. Я понимаю, что это может быть немного излишним, чтобы проверить, как, но я вроде бы понять странное поведение я испытываю:C: Обработка сигналов и семафоры

sig_atomic_t running = 1; 

while(running == 1) { 
    if (sem_wait(server) == -1) { 
     //exit and print error A 
    } 
    if(running == 0) { 
     //exit and print error B 
    } 
    /* do server stuff */ 

    if (sem_post(client) == -1) { 
     //exit and print error 
    } 
} 

сервер это имя семафора сервер, клиент имя клиента семафор (который Безразлично В данном случае это действительно важно. работает (что на самом деле глобальный) является переменной я использую в моем обработчике:

static void init_signalhandler() { 
    struct sigaction sa; 
    sa.sa_handler = terminate; 

    if(sigemptyset(&(sa.sa_mask)) == -1) { 
     bail_out(EXIT_FAILURE, "sigemptyset error"); 
    } 

    if(sigaction(SIGINT, &sa, NULL) == -1) { 
     bail_out(EXIT_FAILURE, "sigaction1 error"); 
    } 

    if(sigaction(SIGTERM, &sa, NULL) == -1) { 
     bail_out(EXIT_FAILURE, "sigaction2 error"); 
    } 
} 

static void terminate(int e) { 
    running = 0; 
    sem_post(server); 
} 

Где bail_out является функцией печати пользовательских ошибок/выходом.

В сущности, независимо от того, что я делаю, всякий раз, когда я запускаю сервер, он добирается до части sem_wait(server). Если я попытаюсь убить его, отправив SIGINT, иногда он печатает ошибку A, а в других случаях он печатает ошибку B. Это кажется совершенно случайным. Это заставляет меня использовать текущую переменную, хотя иногда семафор проходит, а в другое время это не так.

ответ

0

Как вы не обрабатываете EINTR от sem_wait(3), поведение в точности так, как должно быть.

Например, вы ожидаете sem_wait(server). Вы получаете SIGINT и обрабатываете его правильно. Функция sem_wait вернет -1, и вы выручите. Что вы должны сделать вместо этого:

if (sem_wait(s_server) == -1) { 
     if(errno == EINTR) continue; 
     bail_out(EXIT_FAILURE, "sem_wait(3) failed"); 
    } 

Это позволит отлавливать ошибки из-за сигналы в sem_wait рутины, и вы можете завершить свой сервер грациозно, как вы переходите к началу цикла, видите, что ход устанавливается в 0 и пропустите цикл.

См. Страницу руководства sem_wait (3), «Возвращаемые значения» для получения более подробной информации о том, какие ошибки могут быть обработаны.

+0

Но почему тогда он печатает иногда «B»? –

Смежные вопросы