Commit 2c043d29 authored by Kirill Smelkov's avatar Kirill Smelkov

X More effort to unmount failed wcfs.go

Else after first failing tests all furhter test can't start because
trying to stat testmntpt/.wcfs gives ENOTCONN.
parent ab962714
......@@ -96,8 +96,8 @@ LINKC = $(LINK.c) $< $(LOADLIBES) $(LDLIBS) -o $@
# tests without instrumentation
test.t : $(TESTS:%=%.trun)
%.trun : %.t
gdb -q -ex run -ex backtrace -ex quit $(XRUN<)
#$(XRUN<)
#gdb -q -ex run -ex backtrace -ex quit $(XRUN<)
$(XRUN<)
%.t : %.c $(ccan_config)
$(LINKC)
......
......@@ -209,7 +209,7 @@ def _start(zurl, *optv): # -> Conn
while 1:
ret = proc.poll()
if ret is not None:
raise "exited with %s" % ret
raise RuntimeError("exited with %s" % ret)
_, _rx = select(
ctx.done().recv, # 0
......
......@@ -2389,7 +2389,7 @@ func _main() (err error) {
if kinit.Flags & fuse.CAP_EXPLICIT_INVAL_DATA == 0 {
w1 := fmt.Sprintf("%s does not support explicit data cache invalidation", kfuse)
w2 := "-> performance will be AWFUL."
w3 := "-> you need kernel which includes git.kernel.org/linus/ad2ba64dd489 ."
w3 := "-> you need kernel which includes git.kernel.org/linus/ad2ba64dd489."
log.Error(w1); log.Error(w2); log.Error(w3)
fmt.Fprintf(os.Stderr, "W: wcfs: %s\nW: wcfs: %s\nW: wcfs: %s\n", w1, w2, w3)
}
......
......@@ -36,7 +36,8 @@ from ZODB.utils import z64, u64, p64
import sys, os, os.path, subprocess, threading, inspect, traceback, re
from thread import get_ident as gettid
from time import gmtime
from errno import EINVAL
from errno import EINVAL, ENOENT, ENOTCONN
from stat import S_ISDIR
from signal import SIGQUIT, SIGKILL
from golang import go, chan, select, func, defer, default
from golang import context, sync, time
......@@ -87,7 +88,7 @@ def setup_function(f):
# make sure we unmount wcfs after every test.
# (tDB checks this in more detail, but join tests don't use tDB)
def teardown_function(f):
mounted = (0 == subprocess.call(["mountpoint", "-q", testmntpt]))
mounted = is_mountpoint(testmntpt)
if mounted:
subprocess.check_call(["fusermount", "-u", testmntpt])
if os.path.exists(testmntpt):
......@@ -195,12 +196,19 @@ class DFile:
#
# XXX print -> t.trace/debug() + t.verbose depending on py.test -v -v ?
class tDB:
@func
def __init__(t):
t.root = testdb.dbopen()
def _(): # close/unlock db if __init__ fails
exc = sys.exc_info()[1]
if exc is not None:
dbclose(t.root)
defer(_)
assert not os.path.exists(testmntpt)
t.wc = wcfs.join(testzurl, autostart=True)
assert os.path.exists(testmntpt)
assert 0 == subprocess.call(["mountpoint", "-q", testmntpt])
assert is_mountpoint(testmntpt)
# force-unmount wcfs on timeout to unstuck current test and let it fail.
# Force-unmount can be done reliably only by writing into
......@@ -272,32 +280,33 @@ class tDB:
# unmount and wait for wcfs to exit
def _():
assert 0 != subprocess.call(["mountpoint", "-q", testmntpt])
assert not is_mountpoint(testmntpt)
os.rmdir(testmntpt)
defer(_)
def _():
# kill wcfs.go in case it is deadlocked and does not exit by itself
if procwait_(timeout(), t.wc._proc):
return
print("\nC: wcfs.go does not exit")
print("-> kill -QUIT wcfs.go ...\n")
print("\nC: wcfs.go does not exit", file=sys.stderr)
print("-> kill -QUIT wcfs.go ...\n", file=sys.stderr)
os.kill(t.wc._proc.pid, SIGQUIT)
if procwait_(timeout(), t.wc._proc):
return
print("\nC: wcfs.go does not exit (after SIGQUIT)")
print("-> kill -KILL wcfs.go ...\n")
print("\nC: wcfs.go does not exit (after SIGQUIT)", file=sys.stderr)
print("-> kill -KILL wcfs.go ...\n", file=sys.stderr)
os.kill(t.wc._proc.pid, SIGKILL)
if procwait_(timeout(), t.wc._proc):
return
print("\nC: wcfs.go does not exit (after SIGKILL; probably it is stuck in kernel)")
print("-> nothing we can do...\n") # XXX dump /proc/pid/task/*/stack instead (ignore EPERM)
print("\nC: wcfs.go does not exit (after SIGKILL; probably it is stuck in kernel)", file=sys.stderr)
print("-> nothing we can do...\n", file=sys.stderr) # XXX dump /proc/pid/task/*/stack instead (ignore EPERM)
fail("wcfs.go does not exit even after SIGKILL")
defer(_)
def _():
if not ready(t._wcfuseaborted):
assert 0 == subprocess.call(["mountpoint", "-q", testmntpt])
#if not ready(t._wcfuseaborted):
# assert 0 == subprocess.call(["mountpoint", "-q", testmntpt])
assert is_mountpoint(testmntpt)
subprocess.check_call(["fusermount", "-u", testmntpt])
defer(_)
......@@ -2057,6 +2066,27 @@ def procwait_(ctx, proc): # -> ok
raise
return True
# is_mountpoint returns whether path is a mountpoint
def is_mountpoint(path): # -> bool
# NOTE we don't call mountpoint directly on path, because if FUSE
# fileserver failed, the mountpoint will also fail and print ENOTCONN
try:
_ = os.lstat(path)
except OSError as e:
if e.errno == ENOENT:
return False
# "Transport endpoint is not connected" -> it is a failed FUSE server
# (XXX we can also grep /proc/mounts)
if e.errno == ENOTCONN:
return True
raise
if not S_ISDIR(_.st_mode):
return False
mounted = (0 == subprocess.call(["mountpoint", "-q", path]))
return mounted
# xdefer is like defer, but makes sure exception raised before deferred
# function is called is not lost.
......
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