2009-05-27 14 views
6

Piszę program z wątkiem głównym i wątkami roboczymi, i chciałbym, aby obsługa sygnałów była właściwa. Mój problem jest następujący:Wątki master/worker i obsługa sygnałów

rozpoczyna gwint Mistrz i zrobić cały przydział

Mistrz wątek ustawia obsługi sygnału SIGINT

Mistrz wątki uruchomić wątków roboczych. wątki robocze nie wymagają specjalnego czyszczenia, jednak mogą spać podczas wywołania systemowego lub semafora.

Po otrzymaniu SIGINT rozumiem, że otrzymuje go tylko jeden wątek. Więc jeśli wątek śpi w wywołaniu systemowym lub semaforze, nie zostaną one przebudzone i nie będę w stanie wykonać wątków roboczych i wykonać wszystkie niezbędne operacje czyszczenia w głównym wątku.

Czy następujący program obsługi sygnału może rozwiązać mój problem?

void term(int sig) 
{ 
    g_do_cleanup = 1; 
    pthread_kill(worker_1_id, some_other_signal); 
    ... 
    pthread_kill(worker_2_id, some_other_signal); 
} 

Czego oczekuję, że po otrzymaniu SIGINT, cały wątek zostanie zasygnalizowane z innego sygnału, wydostać się z ich blokowania połączeń, zobacz flagę g_do_cleanup i wdzięcznie wyjście.

Każdy komentarz lub link, jak to zrobić poprawnie jest mile widziany.

Edycja: Nie szukam sposobu na przebudzenie wielu wątków oczekujących na konkretny stan, więc nie sądzę, że podejście pthread_cond_signal jest tym, czego szukam. Co chcę jest:

  • Znajdź sposób, że wszystkie nici, które są zablokowany na połączenia blokującego zwraca z tych połączeń.
  • Lub zabij wszystkie wątki z wyjątkiem głównego.

Odpowiedz

4

To, co zazwyczaj robię w głównej aplikacji wątku:


/* before starting other threads */ 
sigset_t sigs; 
sigemptyset(&sigs); 
sigaddset(&sigs, SIGTERM); 
sigaddset(&sigs, SIGINT); 
/* add other signals to handle */ 
if (pthread_sigmask(SIG_BLOCK, &sigs, 0)) { /* handle error */ } 
/* can start threads now */ 
... 
/* in the main event loop */ 
siginfo_t info; 
if (sigwaitinfo(&sigs, &info) == -1) { /* handle error */ } 
switch(info.si_signo) 
{ 
    case SIGTERM: 
    case SIGINT: /* raise shutdown event */ break; 
    default: /* other actions - log rotation, etc. */ 
} 
... 

ten sposób sygnały stają się regularne imprezy aplikacja - bez ograniczeń kontekst specjalny sygnał itp Oczekiwanie może być również wykonane z timeout poprzez sigtimedwait , chociaż pochodne BSD go nie wspierają.

2

Brzmi dla mnie tak, jak chcesz, to zmienna warunku pthread, dzięki czemu możesz obudzić dowolną liczbę wątków, odśpiewując jedno "zdarzenie" z głównego wątku.

Aby uzyskać więcej informacji, zobacz strony podręcznika dla PTHREAD_COND_DESTROY i PTHREAD_COND_BROADCAST.

+0

Tak.Większość ludzi używa implementacji pthread lub Win32/MFC do wykonywania wątków. – Kieveli

+0

Nie, nie sądzę, że jest w porządku, ponieważ nie obudziłaby mnie z blokowania połączenia select lub wywołania sem_wait. Może mógłbym zastąpić moje semafory pthread_condition, ale abstrakcja semaforowa naprawdę pasuje do mojego modelu synchronizacji. – shodanex

1

Twój plan wydaje się być w porządku. Zmuszasz jeden wątek do obsługi sygnałów systemowych. Będziesz musiał maskować sygnały z wyjątkiem jakiegoś innego sygnału w twoich wątkach roboczych za pomocą pthread-sigmask().

Myślę, że chciałbym pójść z oddzielnym wątkiem, aby obsłużyć sygnał procesowy zamiast wzorca. Czy to czekać na zawsze na semaforze lub sigwait() lub cokolwiek, czekając na uruchomienie obsługi sygnału. Przenieś kod pthread-kill z obsługi sygnału. Wystarczy ustawić przełącznik i pozostawić wątek oczekujący na sygnał, wysłać komunikat other_signal do wątków roboczych i wyjść z niego.

+0

Używanie sygnałów do komunikacji między wątkami jest niewłaściwe. wiele bibliotek wątków nawet nie działa z sygnałami. Znacznie lepiej jest używać mechanizmów synchronizacji bieżnika dostarczanych przez bibliotekę wątków, takich jak wspomniane zmienne warunkowe. – lothar

+0

Sygnały są prymitywne i dalekie od ideału, ale jego biblioteka w oczywisty sposób je obsługuje, inaczej nie będzie pytał. Nie robi niczego, co nie zostało zrobione z powodzeniem wiele razy. – Duck

+0

To nie jest tak w przypadku komunikacji wątków, ale także w przypadku terminacji wątków. pthread_cancel + wątek obsługi sygnałów może działać – shodanex