2013-08-24 2 views
1

Я сделал программу с несколькими процессами, каждая из которых имеет ряд потоков. Я хочу остановить программу с помощью ctrl-c и решил использовать обработчик прерываний. Для этого я использовал функцию signal() для установки флага при нажатии ctrl-c. Большинство потоков содержат циклы, которые не имеют в них блокирующего оператора, и просто запускаются, пока флаг не установлен. Когда флаг установлен, цикл заканчивается и вызывается pthread_exit(). Некоторые из потоков содержат оператор блокировки и могут не доходить до того момента, когда замечено изменение флага, и цикл может завершиться.Выход из потока, который содержит оператор блокировки в c

В приведенном ниже примере это приведет к утечке памяти (malloc() без free()) и к процессу, который не был закончен должным образом.

Я проверил много Q & A, но не смог найти подходящее решение. Любая помощь будет принята с благодарностью!

я добавил пример ниже (псевдо-код):

int flag = 0; 

int main(void) 
{ 
    // when (CTRL-C) is pressed, execute the interrupt handler 
    signal(SIGINT, interrupt_handler_STATSERVER); 

    // -- THREAD1: continuously receive packets from the data server 
    pthread_t receivePackets_thread; 
    int rc = pthread_create(&receivePackets_thread, NULL,(void*) receiveFromDataServer, NULL); 
    if (rc) 
    { 
     printf("ERROR; return code from pthread_create() is %d\n", rc); 
     exit(-1); 
    } 
} 


void* receiveFromDataServer(void) 
{ 
    while(flag == 0) 
    { 
     //every loop, allocate memory for a packet 
     packet = (ProcessedPacket*) malloc(sizeof(ProcessedPacket)); 
     if(packet == NULL) 
     { 
      // ERROR: mem allocation error 
     } 
     else 
     { 
      // wait for a connection 
      //*** THE BLOCKING STATEMENT IS HERE *** 
     }  
    } 

    pthread_exit(NULL); 
} 

void interrupt_handler_STATSERVER(int signum) 
{ 
    printf("STAT SERVER INTERRUPT!\n"); 
    flag = 1; 
}` 

ответ

1

Убедитесь, чтобы замаскировать SIGINT на всех дочерних потоков, так как доставка сигнала к одному, произвольной нити без сигнала маскируется. Это гарантирует, что ваш «поток управления» получит ctrl-c. Затем используйте pthread_kill из вашего потока управления, чтобы отправлять сигналы другим потокам с использованием немаркированного сигнала. Это прервет ваши блокирующие вызовы и позволит вам проверять флаги и т. Д.

Прочитайте это: http://man7.org/linux/man-pages/man7/signal.7.html

особенно раздел под названием: Сигнал маски и ожидающие сигналы

Использование pthread_sigmask для проверки и изменения маски сигнала вашего потока.

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