Dlaczego nie mogę zabić procesu SIGSTOP za pomocą SIGTERM i gdzie jest przechowywany oczekujący sygnał?

24

Korzystam z Debiana stretch (systemd). Uruchomiłem demona rsyslog na pierwszym planie /usr/sbin/rsyslogd -n i zrobiłem Ctrl+, Zaby go zatrzymać. Stan procesu zmienił się na Tl(zatrzymany, wątkowy). I wydał kilka poleceń do procesu, a stan procesu była taka sama: . Kiedy to zrobiłem , to umarło. Mam 3 pytania.kill -15 <pid>Tlfg

  • Dlaczego SIGSTOPnie zareagował ten proces SIGTERM? Dlaczego jądro utrzymuje go w tym samym stanie?
  • Dlaczego zginął w momencie otrzymania SIGCONTsygnału?
  • Jeśli było tak z powodu poprzedniego SIGTERMsygnału, to gdzie był on przechowywany aż do wznowienia procesu?
nohup
źródło

Odpowiedzi:

41

SIGSTOPi SIGKILLsą dwoma sygnałami, których proces nie może uchwycić i przetworzyć. SIGTSTPprzypomina SIGSTOPto, że można go złapać i obsłużyć.

SIGSTOPI SIGTSTPsygnały zatrzymania procesu w jego utworów, gotowy SIGCONT. Gdy wyślesz ten proces a SIGTERM, proces nie jest uruchomiony, więc nie można uruchomić kodu, aby wyjść.

(Istnieją również SIGTTINi SIGTTOU, które są sygnałami generowanymi przez warstwę TTY, gdy zadanie w tle próbuje odczytać lub zapisać na terminalu. Można je złapać, ale w przeciwnym razie zatrzymają (zawieszą) proces, tak jak teraz SIGTSTP. Ale teraz idę zignorować tych dwóch do końca tej odpowiedzi).

Twój CtrlZwysyła proces a SIGTSTP, który wydaje się nie być w żaden sposób obsługiwany specjalnie rsyslogd, więc po prostu zawiesza proces w toku SIGCONTlub SIGKILL.

Rozwiązaniem tutaj jest również wysyłanie SIGCONTpo twoim, SIGTERMaby proces mógł odebrać i obsłużyć sygnał.

Przykład:

sleep 999 &

# Assume we got PID 456 for this process
kill -TSTP 456    # Suspend the process (nicely)
kill -TERM 456    # Terminate the process (nicely). Nothing happens
kill -CONT 456    # Continue the process so it can exit cleanly

Dokumentacja biblioteki GNU C wyjaśnia to całkiem dobrze, jak sądzę (moje podkreślenie):

Gdy proces jest zatrzymany, nie można dostarczyć do niego więcej sygnałów, dopóki nie będzie on kontynuowany , z wyjątkiem SIGKILLsygnałów i (oczywiście) SIGCONTsygnałów. Sygnały są oznaczone jako oczekujące, ale nie są dostarczane, dopóki proces nie będzie kontynuowany. Sygnał zawsze powoduje przerwanie procesu i nie może być blokowany, przetwarzane lub ignorowane. Możesz zignorować , ale zawsze powoduje to kontynuowanie procesu, jeśli zostanie zatrzymany. Wysłanie sygnału do procesu powoduje odrzucenie wszelkich oczekujących sygnałów stop dla tego procesu. Podobnie wszelkie oczekujące sygnały dla procesu są odrzucane, gdy odbiera sygnał zatrzymaniaSIGKILLSIGCONTSIGCONTSIGCONT

roaima
źródło
1
@nohup. odpowiedź rozszerzona, ale w zasadzie „tak; obsłużyła to kill -15, co już wysłałeś”.
roaima
2
@ no tak, zgodnie z dokumentacją: « Gdy proces jest zatrzymany, nie można dostarczyć do niego więcej sygnałów, dopóki nie będzie kontynuowany ... Sygnały są oznaczone jako oczekujące, ale nie są dostarczane, dopóki proces nie zostanie kontynuowany. »
roaima
1
Zobacz także SIGTTIN i SIGTTOU, które również zatrzymują procesy
Stéphane Chazelas
1
@ StéphaneChazelas dobry punkt. Dodałem wzmiankę o nich, ale zignorowałem je w inny sposób. Edycja może być dowolna.
roaima
2
@coteyr. Nie zgadzam się: SIGKILLzapobiega czyszczeniu aplikacji, więc używanie SIGTERMjest lepsze w wielu (większości) przypadkach.
roaima
9

SIGTERMjest jak każdy inny sygnał , ponieważ może zostać złapany przez proces. Odbieranie sygnału sprawi, że proces przejdzie do specjalnej procedury obsługi sygnału. Dla SIGTERMdomyślna akcja będzie do zakończenia procesu, ale na przykład redaktor może jak złapać sygnał więc może zapisać projekt kopię wszystkich otwartych plików przed śmiercią. Jeśli proces zostanie zatrzymany, nie będzie można uruchomić procedury obsługi sygnału, ale sygnał pozostanie w oczekiwaniu, aż proces będzie kontynuowany. Zauważ, że liczba wysłanych sygnałów zwykle nie zostanie zapisana.

Teoretycznie system może wiedzieć, czy proces ma zainstalowaną procedurę obsługi sygnałów SIGTERM, i natychmiast ją zakończyć, jeśli nie. Ale (zgodnie z komentarzem Gillesa) POSIX wymaga, aby sygnał był zawieszony, aż proces będzie kontynuowany SIGCONT.

ilkkachu
źródło
4
Przepraszam, mój poprzedni komentarz był błędny. Gdy proces jest zatrzymany, nie są dostarczane żadne sygnały oprócz SIGKILL i SIGCONT. Nawet jeśli sygnał ma domyślną akcję polegającą na zabiciu procesu, jest on opóźniany do momentu wznowienia procesu przez SIGCONT. POSIX nakazuje takie zachowanie.
Gilles 'SO - przestań być zły'