2010-09-29 13 views
17

Używam pthread_create do tworzenia kilku wątków potomnych. W tym samym czasie główny wątek chce zabić wszystkie wątki potomne, albo nastąpi segmentacja. Jaką funkcję powinienem użyć, aby to zakończyć? Przeszukałem odpowiedź od google i otrzymałem funkcję podobną do pthread_kill. Ale nie wiedziałem, jaki sygnał powinienem wysłać do wątku dziecięcego, by je zabić. Moje środowisko pracy to RHEL 5.4, a językiem programowania jest C.Dla pthread, Jak zabić wątek potomny z głównego wątku

+2

wow, zabić wszystkie wątki, ponieważ będzie segfault? żartujesz? Nigdy nie za pomocą kodu, który jest obsługiwany w ten sposób. –

+1

Powiedziawszy, gdb znalazłem zrzut pamięci znaleziony podczas dekonstrukcji głównego obiektu wyjścia globalnego wątku. Dlatego niektóre wątki potomne mogą obecnie używać takiej zmiennej, a błąd segmentu jest drukowany na moim ekranie. Chociaż logika jest właściwa, a błąd segmentu nie będzie miał żadnego wpływu na mój program, ponieważ jest on zakończony. – terry

+2

Napraw logikę. Jeśli inne wątki nadal wykonują pożyteczną pracę, dlaczego próbujesz zakończyć program? Jeśli pozostałe wątki nadal potrzebują tych obiektów, nawet gdy 'main' wykracza poza zakres, dlaczego są one przydzielane na stosie' main'? –

Odpowiedz

20

Możliwe jest "anulowanie" wątku za pomocą pthread_cancel. Nie jest to jednak najlepsza praktyka, chociaż w ekstremalnych okolicznościach, takich jak SEGFAULT, można przyjąć rozsądne podejście.

+1

Istnieje przykład w tym adresie URL http://linux.die.net/man/3/pthread_cleanup_push – enthusiasticgeek

+4

Dlaczego "pthread_cancel" nie jest uważane za najlepszą praktykę? A jeśli nie jest to najlepsza praktyka, co to jest? – darnir

6

należy wysłać SIG_TERM do każdego z wątków, używając

int pthread_kill(pthread_t thread, int sig); 

Szybkim sposobem, aby pozbyć się wszystkich wątków (oprócz głównego) jest fork() i iść z dzieckiem.
Nie hiper czysty ...

if (fork()) exit(0); // deals also with -1... 
24

W ogóle, tak naprawdę nie chcą brutalnie zabić wątku dziecko, ale zamiast tego chcesz poprosić go, aby zakończyć. W ten sposób możesz być pewien, że dziecko rzuca się w bezpieczne miejsce i wszystkie jego zasoby są oczyszczone.

Zwykle robię to z małym kawałkiem stanu współdzielonego między rodzicem a dzieckiem, aby umożliwić rodzicowi przekazanie każdemu dziecku "prośby o zamknięcie". Może to być wartość boolowska dla każdego dziecka, chroniona przez muteks. Dziecko okresowo sprawdza tę wartość (każda iteracja pętli lub inne dogodne punkty kontrolne w wątku potomnym). Po stwierdzeniu, że "quit_request" jest prawdziwe, wątek potomny czyści się i wywołuje pthread_exit.

Na stronie dominującego, „kill_child” rutyna wygląda mniej więcej tak:

acquire shared mutex 
set quit_request to true 
pthread_join the child 

pthread_join może zająć trochę czasu, w zależności od tego, jak często dziecko sprawdza zakończyć żądania. Upewnij się, że twój projekt poradzi sobie bez względu na opóźnienie.

+0

Chociaż na ogół dobrą praktyką jest nabywanie muteksu przed modyfikacją pamięci współużytkowanej między wątkami, fakt, że jest to pojedyncza flaga, która jest sprawdzana pod kątem niezerowego (lub fałszywego) statusu, oznacza, że ​​naprawdę nie potrzebujesz złapać muteksa. W tym przypadku naprawdę niewiele może się wydarzyć z perspektywy spójności danych. –

+2

@Brent: [To pytanie] (http://stackoverflow.com/questions/21183261/is-a-race-condition-possible-when-only-one-thread-writes-to-a-bool-variable-in -c) pokazuje przykład, w którym nawet pojedyncza flaga napisana raz może doprowadzić do stanu wyścigowego po optymalizacji kompilatora. – dshepherd

+0

Piękne, działa to cudownie. – djthoms

2

Możesz użyć zmiennej globalnej dla całego programu.

int _fCloseThreads;

Ustaw 1, aby wątki zakończyły wykonywanie. Niech wątki sprawdzą tę zmienną w swojej "pętli" i ładnie zakończą działanie, gdy ustawiona jest na 1. Nie trzeba jej chronić za pomocą muteksu.

Musisz poczekać na zamknięcie wątków. Możesz użyć join. Innym sposobem jest zwiększenie licznika, gdy wątek wchodzi w jego wątek proc, a następnie zmniejsza licznik, gdy opuszcza. Licznik musiałby być globalny. Użyj licznika atomowego gcc na liczniku. Główny wątek, po ustawieniu fCloseThreads, może czekać na licznik, aby przejść do zera przez zapętlenie, spanie i sprawdzenie liczby.

Wreszcie, możesz sprawdzić pthread_cleanup_push i pop. Są one modelem umożliwiającym wątkowi anulowanie dowolnego miejsca w jego kodzie (używa longjump), a następnie wywołanie funkcji końcowego czyszczenia przed zakończeniem wątku. Najpierw umieść cleanup_push na górze wątku i cleanup_pop na dole, utwórz funkcję rozwijania, a następnie w pewnych punktach anulowania wątek anulowany przez wywołanie pthread_cancel() spowoduje powrót do threadproc i wywołanie funkcji unwind.

+1

http://linux.die.net/man/3/pthread_cleanup_push ma przykład. – enthusiasticgeek

Powiązane problemy