Commit 153c002a authored by Kirill Smelkov's avatar Kirill Smelkov

X wcfs: _fuse_unmount: Try first `kill -TERM` before `kill -QUIT` wcfs

Just aborting the FUSE connection does not make WCFS to exit. This abort
is needed to avoid deadlocks, but we should also signal WCFS it should
stop. Not doing so will lead to timeout in wait after FUSE connection
abort and `kill -QUIT` triggered, which makes WCFS crash and print lots
of traceback to stderr before exiting.
parent 15389db0
......@@ -71,7 +71,7 @@ import logging as log
from os.path import dirname
from stat import S_ISDIR
from errno import ENOENT, ENOTCONN, EEXIST
from signal import SIGQUIT, SIGKILL
from signal import SIGTERM, SIGQUIT, SIGKILL
from golang import chan, select, default, func, defer
from golang import context, errors, sync, time
......@@ -423,41 +423,43 @@ def __stop(wcsrv, ctx, _onstuck):
if _procwait_(timeoutFrac(0.5), wcsrv._proc):
return
log.warn("\nC: wcfs.go does not exit")
log.warn("-> kill -QUIT wcfs.go ...\n")
log.warn("wcfs.go does not exit (after SIGTERM)")
log.warn("-> kill -QUIT wcfs.go ...")
os.kill(wcsrv._proc.pid, SIGQUIT)
if _procwait_(timeoutFrac(0.25), wcsrv._proc):
return
log.warn("\nC: wcfs.go does not exit (after SIGQUIT)")
log.warn("-> kill -KILL wcfs.go ...\n")
log.warn("wcfs.go does not exit (after SIGQUIT)")
log.warn("-> kill -KILL wcfs.go ...")
os.kill(wcsrv._proc.pid, SIGKILL)
if _procwait_(timeoutFrac(0.25), wcsrv._proc):
return
log.warn("\nC: wcfs.go does not exit (after SIGKILL; probably it is stuck in kernel)")
log.warn("-> nothing we can do...\n") # XXX dump /proc/pid/task/*/stack instead (ignore EPERM)
log.warn("wcfs.go does not exit (after SIGKILL; probably it is stuck in kernel)")
log.warn("-> nothing we can do...") # XXX dump /proc/pid/task/*/stack instead (ignore EPERM)
if _onstuck is not None:
_onstuck()
else:
_procwait(context.background(), wcsrv._proc)
defer(_)
@func
def _():
try:
if _is_mountpoint(wcsrv.mountpoint): # could be unmounted from outside
_fuse_unmount(wcsrv.mountpoint)
except:
# if clean unmount failed -> force abort of fuse connection
def _():
if wcsrv._fuseabort is not None:
log.warn("aborting FUSE connection ...")
wcsrv._fuseabort.write(b"1\n")
wcsrv._fuseabort.flush()
defer(_)
raise
defer(_)
try:
if _is_mountpoint(wcsrv.mountpoint): # could be unmounted from outside
_fuse_unmount(wcsrv.mountpoint)
except:
# if clean unmount failed -> kill -TERM wcfs and force abort of fuse connection.
#
# aborting fuse connection is needed in case wcfs/kernel will be stuck
# in a deadlock even after being `kill -9`. See comments in tWCFS for details.
def _():
log.warn("-> kill -TERM wcfs.go ...")
os.kill(wcsrv._proc.pid, SIGTERM)
if wcsrv._fuseabort is not None:
log.warn("-> aborting FUSE connection ...")
wcsrv._fuseabort.write(b"1\n")
wcsrv._fuseabort.flush()
defer(_)
raise
# ---- misc ----
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment