2016-04-15 1 views
1

Я пишу программу C на Linux, где у меня есть основной() и два созданных им pthreads. В одном из pthreads у меня есть вызов функции accept().Функция блокировки accept() перезапускается, когда SIGINT происходит, даже если флаг SA_RESTART установлен на ноль

У меня есть обработчик сигнала, который вызывается при получении SIGINT, SIGQUIT или SIGTERM.

Я ожидаю, потому что я делаю флаг SA_RESTART ноль, когда я нажимаю ctrl-c, функция accept() возвращает EINTR вместо перезапуска, однако я понял через связку вызовов printf во время отладки (чтобы увидеть, какие строки выполняются путем печати, где находится код), что хотя мое приложение может захватить SIGINT, функция accept остается заблокированной, она не прерывается с EINTR и не переходит к следующей строке кода. Вот мои настройки внутри основной()

struct sigaction signal_action; 
signal_action.sa_flags = 0; // Don't restart the blocking call after it failed with EINTR 
signal_action.sa_handler = terminate; 
sigemptyset(&signal_action.sa_mask); 
sigfillset(&signal_action.sa_mask); // Block every signal during the handler is executing 
if (sigaction(SIGINT, &signal_action, NULL) < 0) { 
    perror("error handling SIGINT"); 
} 
if (sigaction(SIGTERM, &signal_action, NULL) < 0) { 
    perror("error handling SIGTERM"); 
} 
if (sigaction(SIGQUIT, &signal_action, NULL) < 0) { 
    perror("error handling SIGQUIT"); 
} 

Вот обработчик сигнала:

void terminate (int signum) 
{ 
    terminate_program = 1; 
    printf("Terminating.\n"); 
} 

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

void* pthread_timerless_socket_tasks(void* parameter) 
{ 

    server_socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if(server_socket_fd < 0) 
    { 
     perror("error creating IPv4 TCP stream socket"); 
     return (NULL); 
    } 
    printf("socket created\n"); // for debugging 
    if(fcntl(server_socket_fd, F_SETFL, 0) < 0) 
    { 
     perror("error making socket_fd blocking"); 
     close(server_socket_fd); 
     return (NULL); 
    } 

    while(!terminate_program) 
    { 
     printf("socket blocking on accept\n"); // for debugging 
     client_socket_fd = accept(server_socket_fd,(struct sockaddr *) &client_address, &client_length); 
     printf("socket accepted?\n"); // for debugging 
     if(client_socket_fd < 0) 
     { 
      perror("error accepting socket_fd"); 
      close(server_socket_fd); 
      return (NULL); 
     } 


    } 

Надеюсь, я ясно дал понять.

Итак, теперь я задаюсь вопросом, что отсутствует или неверно, поскольку я не могу увидеть поведение, описанное в руководствах linux для SA_RESTART.

+0

Это 'if (fcntl (server_socket_fd, F_SETFL, 0) ...' выглядит странно, чтобы не сказать неправильно. – alk

+0

@alk Я пытался сделать файловый дескриптор блокирующим таким образом, поскольку по умолчанию это не так. Я открыт для предложений :) – etugcey

+0

О том, как переключиться в состояние блокировки сокета с помощью 'fcntl()', возможно, вам понравился этот ответ: http://stackoverflow.com/a/1549344/694576 – alk

ответ

5

От the signal(7) manual page:

Если более чем один из потоков имеет разблокирован сигнал, то ядро ​​выбирает произвольную нить, к которой для доставки сигнала.

Что это означает, что если сигнал не отправляется в поток, выполняющий accept, тогда вызов не прерывается сигналом.

Вы должны заблокировать (путем установки сигнальной маски) сигналы во всех других потоках, тогда единственным потоком, который может принимать сигнал, является тот, который вызывает accept.

+0

Я переместил код «настроек» (где я вызываю sigaction и устанавливаю sa_flags в ноль) из main() в поток с accept() (и удостоверился, что ни один другой поток не имеет этого кода), чтобы убедиться, что сигнал доставлен в нужную цепочку, но все равно accept() блокирует. – etugcey

+0

Я понял из вашего поста, мне нужно также блокировать другие потоки, я попробую сейчас. – etugcey

+0

@etugcey Откройте страницу сопряженной ссылки и выполните поиск «Сигнальная маска и ожидающие сигналы». Это скажет вам, какие функции вам необходимо блокировать и разблокировать сигналы для каждого процесса и потока. –

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