Załóżmy, że mamy taki trywialny demon napisany w pythonie:
def mainloop():
while True:
# 1. do
# 2. some
# 3. important
# 4. job
# 5. sleep
mainloop()
i demonizujemy go, używając start-stop-daemon
domyślnie włączonego sygnału SIGTERM
( TERM
) --stop
.
Załóżmy, że aktualnie wykonywany krok to #2
. I w tej chwili wysyłamy TERM
sygnał.
Dzieje się tak, że wykonanie kończy się natychmiast.
Przekonałem się, że mogę obsłużyć zdarzenie sygnałowe, signal.signal(signal.SIGTERM, handler)
ale chodzi o to, że nadal przerywa ono bieżące wykonanie i przekazuje kontrolę handler
.
Zatem moje pytanie brzmi - czy można nie przerywać bieżącego wykonania, ale obsługiwać TERM
sygnał w oddzielnym wątku (?), Aby móc ustawić shutdown_flag = True
tak, aby mainloop()
miał szansę zatrzymać się z gracją?
python
daemon
sigterm
start-stop-daemon
zerkms
źródło
źródło
signalfd
prosiłeś, wykorzystując i maskując dostawęSIGTERM
do procesu.Odpowiedzi:
Czyste w użyciu rozwiązanie oparte na klasie:
źródło
False
Wartość jest ustawiona tylko raz, a następnie można przejść tylko z false na true tak Multiple Access nie jest problemem.Po pierwsze, nie jestem pewien, czy potrzebujesz drugiego wątku, aby ustawić
shutdown_flag
.Dlaczego nie ustawić go bezpośrednio w module obsługi SIGTERM?
Alternatywą jest zgłoszenie wyjątku od modułu
SIGTERM
obsługi, który będzie propagowany w górę stosu. Zakładając, że masz odpowiednią obsługę wyjątków (np. Zwith
/contextmanager
itry: ... finally:
blokami), powinno to być dość płynne zamknięcie, podobnie jak w przypadku Ctrl+Ctwojego programu.Przykładowy program
signals-test.py
:Teraz zobacz Ctrl+Czachowanie:
Tym razem wysyłam go
SIGTERM
po 4 iteracjach zkill $(ps aux | grep signals-test | awk '/python/ {print $2}')
:Tym razem włączam mój niestandardowy
SIGTERM
moduł obsługi i wysyłam goSIGTERM
:źródło
Myślę, że jesteś blisko możliwego rozwiązania.
Wykonaj
mainloop
w osobnym wątku i rozszerz go o właściwośćshutdown_flag
. Sygnał może zostać przechwyconysignal.signal(signal.SIGTERM, handler)
w głównym wątku (nie w oddzielnym wątku). Procedura obsługi sygnału powinna mieć wartośćshutdown_flag
True i czekać na zakończenie wątkuthread.join()
źródło
Oto prosty przykład bez wątków i klas.
źródło
Na podstawie poprzednich odpowiedzi stworzyłem menedżera kontekstu, który chroni przed sigint i sigterm.
źródło
Znaleziono dla mnie najprostszy sposób. Oto przykład z widelcem dla jasności, że ten sposób jest użyteczny do kontroli przepływu.
źródło
Najprostszym rozwiązaniem, jakie znalazłem, czerpiąc inspirację z powyższych odpowiedzi jest
źródło