Jak mogę zabić konkretny wątek procesu?

21
$ ps -e -T | grep myp | grep -v grep
  797   797 ?        00:00:00 myp
  797   798 ?        00:00:00 myp
  797   799 ?        00:00:00 myp
  797   800 ?        00:00:00 myp

To pokazuje proces mypz PID = 797 i czterema wątkami o różnych SPID.

Jak mogę zabić konkretny wątek procesu bez zabijania całego procesu. Rozumiem, że w niektórych przypadkach może nie być to możliwe, gdy istnieją fatalne zależności od tego konkretnego wątku. Ale czy w każdym razie jest to możliwe? Czy tak, jak?

Próbowałem kill 799i sam proces został zakończony. Teraz nie jestem pewien, czy było tak dlatego, że istniały zależności, które mypzawiodły bez procesu 800lub ponieważ zabicie jest po prostu niemożliwe do zabicia poszczególnych procesów.

Lazer
źródło

Odpowiedzi:

26

Wątki są integralną częścią procesu i nie można ich zabić poza nim. Istnieje funkcja pthread_kill, ale ma ona zastosowanie tylko w kontekście samego wątku. Z dokumentów pod linkiem:

Zauważ, że pthread_kill () powoduje, że sygnał jest obsługiwany tylko w kontekście danego wątku; działanie sygnału (zakończenie lub zatrzymanie) wpływa na cały proces.

gvkv
źródło
+1. aby dodać tutaj. w ramach tego procesu możesz użyć pthread_kill () do wysyłania sygnałów do poszczególnych wątków. być może możesz dodać program obsługi sygnału, który to robi.
Hemant,
@hemant: Załóżmy, że MS Word używa osobnego wątku do sprawdzania pisowni. Zabicie tego wątku nie powinno doprowadzić do upadku, chyba że jest tak zaprojektowane. Dlaczego proces nie może istnieć bez tego wątku w takich sytuacjach?
Lazer
1
Cóż, przypuszczam, że możesz zaprojektować model wątków, który będzie niezależny od procesu nadrzędnego, ale umożliwiając zewnętrznym procesom zabijanie wątków wewnątrzprocesowych, ale to otwiera puszkę robaków w odniesieniu do bezpieczeństwa, zarządzania procesami i integralności systemu, którego nie „ Myślę, że każdy projektant systemu chętnie się podda. Gwintowanie jest wystarczająco trudne bez tego rodzaju bólów głowy. Zabicie wątku od wewnątrz nie stanowi problemu, ponieważ praca jest wykonywana przez proces nadrzędny, który jest odpowiedzialny za ewentualne problemy i może zostać zabity - automatycznie lub w inny sposób.
gvkv
„chyba że jest tak zaprojektowany”: Głównym powodem używania wątków jest właśnie to, że możesz udostępniać zasoby. To raczej jak zburzenie połowy domu.
pjc50
2
@ Lazer, jeden wątek nie może sprawdzić pisowni w tym samym czasie, co inny wątek aktualizuje tekst, ponieważ piszesz. Z tego powodu, aby mieć wątek sprawdzający pisownię w tle, musi zrobić coś takiego jak złapanie zamka, aby zapobiec zmianie tekstu przez inny wątek, wykonanie kopii niektórych słów, zwolnienie blokady, a następnie sprawdzenie skopiowanych słów w tło. Jeśli zdarzy ci się go zabić, gdy trzyma zamek, zawiesisz drugi wątek, gdy tylko spróbujesz pisać. Aplikacje wielowątkowe są pełne takich zależności między sobą.
psusi
6

Kanoniczna odpowiedź na to pytanie brzmi: przy współpracy procesu, niezależnie od mechanizmu, jaki zapewnia. Bez współpracy procesu jest to niemożliwe. To, że proces składa się z wątków, jest wewnętrznym szczegółem procesu, który zgodnie z zamierzonym projektem nie jest odsłonięty poza procesem.

David Schwartz
źródło
A co z wysyłaniem innych sygnałów z wiersza poleceń?
yucer
@yucer Nie jestem pewien, czy rozumiem, o co pytasz.
David Schwartz
Mam na myśli wysłanie kolejnego sygnału z listy pokazanej jako „kill -l”. Szukam sposobu na polecenie określonego wątku, aby zrzucić ślad stosu, aby zobaczyć, co robi.
yumper
@yucer To będzie specyficzne dla platformy. Niektóre udostępniają sposób polecenia określonego wątku, aby zrzucić stos. Osobiście uważam, że łatwiej jest po prostu użyć skryptu, aby dołączyć debuger (podobny gdb) do procesu, nakazać wszystkim wątkom zrzucić stos, a następnie odłączyć.
David Schwartz
1

Oprócz odpowiedzi @ gkv możesz spojrzeć na funkcję pthread_cancel(3), część <pthread.h>. Ze strony podręcznika:

Funkcja pthread_cancel () wysyła żądanie anulowania do wątku wątku. To, czy i kiedy docelowy wątek zareaguje na żądanie anulowania, zależy od dwóch atrybutów kontrolowanych przez ten wątek: jego stanu i typu anulowania.

Ivan P.
źródło
1

Może się przydać tgkill () . Jest specyficzny dla Linuksa, jak wspomina strona man.

tgkill () wysyła sygnał sig do wątku z identyfikatorem wątku tid w grupie wątków tgid. (Z drugiej strony, kill (2) może być użyty tylko do wysłania sygnału do procesu (tj. Grupy wątków) jako całości, a sygnał zostanie dostarczony do dowolnego wątku w ramach tego procesu.)

Amit
źródło
Nie dotyczy to pytania o to, jak zabić wątek, a nie jak wysłać sygnał do wątku.
David Schwartz