[Python 3 only] Changed SIGTERM signal handling.

Now the first SIGTERM will propagate a SIGINT to child processes.

A second SIGTERM signal would send a SIGTERM to child processes and "interrupt" itself.

A third SIGTERM signal would actually follow the default system behaviour.

# Conflicts:
#	bazarr.py
pull/922/head
Smaarn 5 years ago
parent 93b95f9936
commit 2ee437e45b

@ -55,34 +55,6 @@ class DaemonStatus(ProcessRegistry):
def unregister(self, process): def unregister(self, process):
self.__processes.remove(process) self.__processes.remove(process)
@staticmethod
def __wait_for_processes(processes, timeout):
"""
Waits all the provided processes for the specified amount of time in seconds.
"""
reference_ts = time.time()
elapsed = 0
remaining_processes = list(processes)
while elapsed < timeout and len(remaining_processes) > 0:
remaining_time = timeout - elapsed
for ep in list(remaining_processes):
if ep.poll() is not None:
remaining_processes.remove(ep)
else:
if remaining_time > 0:
if PY3:
try:
ep.wait(remaining_time)
remaining_processes.remove(ep)
except subprocess.TimeoutExpired:
pass
else:
# In python 2 there is no such thing as some mechanism to wait with a timeout
time.sleep(1)
elapsed = time.time() - reference_ts
remaining_time = timeout - elapsed
return remaining_processes
@staticmethod @staticmethod
def __send_signal(processes, signal_no, live_processes=None): def __send_signal(processes, signal_no, live_processes=None):
""" """
@ -105,9 +77,11 @@ class DaemonStatus(ProcessRegistry):
Flags this instance as should stop and terminates as smoothly as possible children processes. Flags this instance as should stop and terminates as smoothly as possible children processes.
""" """
self.__should_stop = True self.__should_stop = True
live_processes = DaemonStatus.__send_signal(self.__processes, signal.SIGINT, list()) DaemonStatus.__send_signal(self.__processes, signal.SIGINT, list())
live_processes = DaemonStatus.__wait_for_processes(live_processes, 120)
DaemonStatus.__send_signal(live_processes, signal.SIGTERM) def force_stop(self):
self.__should_stop = True
DaemonStatus.__send_signal(self.__processes, signal.SIGTERM)
def should_stop(self): def should_stop(self):
return self.__should_stop return self.__should_stop
@ -170,11 +144,19 @@ if __name__ == '__main__':
if PY3: if PY3:
daemonStatus = DaemonStatus() daemonStatus = DaemonStatus()
def force_shutdown():
# force the killing of children processes
daemonStatus.force_stop()
# if a new SIGTERM signal is caught the standard behaviour should be followed
signal.signal(signal.SIGTERM, signal.SIG_DFL)
# emulate a Ctrl C command on itself (bypasses the signal thing but, then, emulates the "Ctrl+C break")
os.kill(os.getpid(), signal.SIGINT)
def shutdown(): def shutdown():
# indicates that everything should stop # indicates that everything should stop
daemonStatus.stop() daemonStatus.stop()
# emulate a Ctrl C command on itself (bypasses the signal thing but, then, emulates the "Ctrl+C break") # if a new sigterm signal is caught it should force the shutdown of children processes
os.kill(os.getpid(), signal.SIGINT) signal.signal(signal.SIGTERM, lambda signal_no, frame: force_shutdown())
signal.signal(signal.SIGTERM, lambda signal_no, frame: shutdown()) signal.signal(signal.SIGTERM, lambda signal_no, frame: shutdown())

Loading…
Cancel
Save