Reloader cleanup, don't use external kill commands and exit normally.
This commit is contained in:
parent
2cb410705d
commit
e522c722fa
@ -1116,7 +1116,7 @@ class Sanic:
|
|||||||
|
|
||||||
if auto_reload or auto_reload is None and debug:
|
if auto_reload or auto_reload is None and debug:
|
||||||
if os.environ.get("SANIC_SERVER_RUNNING") != "true":
|
if os.environ.get("SANIC_SERVER_RUNNING") != "true":
|
||||||
return reloader_helpers.watchdog(2)
|
return reloader_helpers.watchdog(1.0)
|
||||||
|
|
||||||
if sock is None:
|
if sock is None:
|
||||||
host, port = host or "127.0.0.1", port or 8000
|
host, port = host or "127.0.0.1", port or 8000
|
||||||
|
@ -56,105 +56,45 @@ def restart_with_reloader():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def kill_process_children_unix(pid):
|
|
||||||
"""Find and kill child processes of a process (maximum two level).
|
|
||||||
|
|
||||||
:param pid: PID of parent process (process ID)
|
|
||||||
:return: Nothing
|
|
||||||
"""
|
|
||||||
root_process_path = "/proc/{pid}/task/{pid}/children".format(pid=pid)
|
|
||||||
if not os.path.isfile(root_process_path):
|
|
||||||
return
|
|
||||||
with open(root_process_path) as children_list_file:
|
|
||||||
children_list_pid = children_list_file.read().split()
|
|
||||||
|
|
||||||
for child_pid in children_list_pid:
|
|
||||||
children_proc_path = "/proc/%s/task/%s/children" % (
|
|
||||||
child_pid,
|
|
||||||
child_pid,
|
|
||||||
)
|
|
||||||
if not os.path.isfile(children_proc_path):
|
|
||||||
continue
|
|
||||||
with open(children_proc_path) as children_list_file_2:
|
|
||||||
children_list_pid_2 = children_list_file_2.read().split()
|
|
||||||
for _pid in children_list_pid_2:
|
|
||||||
try:
|
|
||||||
os.kill(int(_pid), signal.SIGTERM)
|
|
||||||
except ProcessLookupError:
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
os.kill(int(child_pid), signal.SIGTERM)
|
|
||||||
except ProcessLookupError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
|
|
||||||
def kill_process_children_osx(pid):
|
|
||||||
"""Find and kill child processes of a process.
|
|
||||||
|
|
||||||
:param pid: PID of parent process (process ID)
|
|
||||||
:return: Nothing
|
|
||||||
"""
|
|
||||||
subprocess.run(["pkill", "-P", str(pid)])
|
|
||||||
|
|
||||||
|
|
||||||
def kill_process_children(pid):
|
|
||||||
"""Find and kill child processes of a process.
|
|
||||||
|
|
||||||
:param pid: PID of parent process (process ID)
|
|
||||||
:return: Nothing
|
|
||||||
"""
|
|
||||||
if sys.platform == "darwin":
|
|
||||||
kill_process_children_osx(pid)
|
|
||||||
elif sys.platform == "linux":
|
|
||||||
kill_process_children_unix(pid)
|
|
||||||
else:
|
|
||||||
pass # should signal error here
|
|
||||||
|
|
||||||
|
|
||||||
def kill_program_completely(proc):
|
|
||||||
"""Kill worker and it's child processes and exit.
|
|
||||||
|
|
||||||
:param proc: worker process (process ID)
|
|
||||||
:return: Nothing
|
|
||||||
"""
|
|
||||||
kill_process_children(proc.pid)
|
|
||||||
proc.terminate()
|
|
||||||
os._exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
def watchdog(sleep_interval):
|
def watchdog(sleep_interval):
|
||||||
"""Watch project files, restart worker process if a change happened.
|
"""Watch project files, restart worker process if a change happened.
|
||||||
|
|
||||||
:param sleep_interval: interval in second.
|
:param sleep_interval: interval in second.
|
||||||
:return: Nothing
|
:return: Nothing
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def interrupt_self(*args):
|
||||||
|
raise KeyboardInterrupt
|
||||||
|
|
||||||
mtimes = {}
|
mtimes = {}
|
||||||
|
signal.signal(signal.SIGTERM, interrupt_self)
|
||||||
worker_process = restart_with_reloader()
|
worker_process = restart_with_reloader()
|
||||||
signal.signal(
|
|
||||||
signal.SIGTERM, lambda *args: kill_program_completely(worker_process)
|
|
||||||
)
|
|
||||||
signal.signal(
|
|
||||||
signal.SIGINT, lambda *args: kill_program_completely(worker_process)
|
|
||||||
)
|
|
||||||
while True:
|
|
||||||
need_reload = False
|
|
||||||
|
|
||||||
for filename in _iter_module_files():
|
try:
|
||||||
try:
|
while True:
|
||||||
mtime = os.stat(filename).st_mtime
|
need_reload = False
|
||||||
except OSError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
old_time = mtimes.get(filename)
|
for filename in _iter_module_files():
|
||||||
if old_time is None:
|
try:
|
||||||
mtimes[filename] = mtime
|
mtime = os.stat(filename).st_mtime
|
||||||
elif mtime > old_time:
|
except OSError:
|
||||||
mtimes[filename] = mtime
|
continue
|
||||||
need_reload = True
|
|
||||||
|
|
||||||
if need_reload:
|
old_time = mtimes.get(filename)
|
||||||
kill_process_children(worker_process.pid)
|
if old_time is None:
|
||||||
worker_process.terminate()
|
mtimes[filename] = mtime
|
||||||
worker_process = restart_with_reloader()
|
elif mtime > old_time:
|
||||||
|
mtimes[filename] = mtime
|
||||||
|
need_reload = True
|
||||||
|
|
||||||
sleep(sleep_interval)
|
if need_reload:
|
||||||
|
worker_process.terminate()
|
||||||
|
worker_process.wait()
|
||||||
|
worker_process = restart_with_reloader()
|
||||||
|
|
||||||
|
sleep(sleep_interval)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
worker_process.terminate()
|
||||||
|
worker_process.wait()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user