From 1a4a6350a9033f0c2d1e2b7e6c1a029bdaa46da6 Mon Sep 17 00:00:00 2001 Message-Id: <1a4a6350a9033f0c2d1e2b7e6c1a029bdaa46da6.1715165560.git.mdw@distorted.org.uk> From: Mark Wooding Date: Thu, 22 Nov 2007 11:35:34 +0000 Subject: [PATCH] The initial rescan now blocks any client connections. This means that a deadlock is unlikely to arise in the initial scan. It also means that the server is not usable for a short period after startup (or quite a long period after initial startup, but that's less of a problem). Organization: Straylight/Edgeware From: Richard Kettlewell The tests now take advantage of this by waiting until the socket appears before assuming the daemon has started. --- server/disorderd.c | 7 +++++-- server/trackdb.c | 14 +++++++++++--- tests/alltests | 2 +- tests/dtest.py | 29 +++++++++++++++++++++++++++-- tests/nothing.py | 3 +-- tests/version.py | 1 - 6 files changed, 45 insertions(+), 11 deletions(-) diff --git a/server/disorderd.c b/server/disorderd.c index e8e1046..758907c 100644 --- a/server/disorderd.c +++ b/server/disorderd.c @@ -289,8 +289,11 @@ int main(int argc, char **argv) { /* ignore SIGPIPE */ signal(SIGPIPE, SIG_IGN); /* start a rescan straight away */ - if(initial_rescan) - trackdb_rescan(ev); + if(initial_rescan) { + trackdb_rescan(0/*ev*/); + /* No ev -> the rescan will block. Since we called reconfigure() already + * any clients will also be forced to block. */ + } rescan_after(86400); /* periodically tidy up the database */ dbgc_after(60); diff --git a/server/trackdb.c b/server/trackdb.c index 8cfd71f..57ebb68 100644 --- a/server/trackdb.c +++ b/server/trackdb.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "event.h" #include "mem.h" @@ -1826,14 +1827,21 @@ static int reap_rescan(ev_source attribute((unused)) *ev, } void trackdb_rescan(ev_source *ev) { + int w; if(rescan_pid != -1) { error(0, "rescan already underway"); return; } rescan_pid = subprogram(ev, RESCAN, -1); - ev_child(ev, rescan_pid, 0, reap_rescan, 0); - D(("started rescanner")); - + if(ev) { + ev_child(ev, rescan_pid, 0, reap_rescan, 0); + D(("started rescanner")); + } else { + /* This is the first rescan, we block until it is complete */ + while(waitpid(rescan_pid, &w, 0) < 0 && errno == EINTR) + ; + reap_rescan(0, rescan_pid, w, 0, 0); + } } int trackdb_rescan_cancel(void) { diff --git a/tests/alltests b/tests/alltests index b115f7d..812b53a 100755 --- a/tests/alltests +++ b/tests/alltests @@ -56,7 +56,7 @@ for f in os.listdir(testdir): tests.sort() # let's have a consistent order for test in tests: - print "Test '%s'" % test + print "-------- Test '%s' --------" % test dtest.run(test, report=False) print "%d tests" % dtest.tests diff --git a/tests/dtest.py b/tests/dtest.py index 38c7219..6ae9fd7 100644 --- a/tests/dtest.py +++ b/tests/dtest.py @@ -21,7 +21,7 @@ """Utility module used by tests""" -import os,os.path,subprocess,sys,re +import os,os.path,subprocess,sys,re,time def fatal(s): """Write an error message and exit""" @@ -137,12 +137,34 @@ Start the daemon.""" global daemon, errs assert daemon == None print " starting daemon" + # remove the socket if it exists + socket = "%s/socket" % testroot + try: + os.remove(socket) + except: + pass daemon = subprocess.Popen(["disorderd", "--foreground", "--config", "%s/config" % testroot], stderr=errs) disorder._configfile = "%s/config" % testroot disorder._userconf = False + # Wait for the socket to be created + waited = 0 + while not os.path.exists(socket): + rc = daemon.poll() + if rc is not None: + print "FATAL: daemon failed to start up" + sys.exit(1) + waited += 1 + if waited == 1: + print " waiting for socket..." + elif waited >= 60: + print "FATAL: took too long for socket to appear" + sys.exit(1) + time.sleep(1) + if waited > 0: + print " took about %ds for socket to appear" % waited def stop_daemon(): """stop_daemon() @@ -155,8 +177,11 @@ Stop the daemon if it has not stopped already""" if rc == None: print " stopping daemon" os.kill(daemon.pid, 15) + print " waiting for daemon" rc = daemon.wait() - print " daemon has stopped" + print " daemon has stopped" + else: + print " daemon already stopped" daemon = None def run(module=None, report=True): diff --git a/tests/nothing.py b/tests/nothing.py index f3bdeb9..c12443e 100755 --- a/tests/nothing.py +++ b/tests/nothing.py @@ -21,9 +21,8 @@ import dtest,time def test(): - """Just start the server and then stop it a few seconds later""" + """Just start the server and then stop it""" dtest.start_daemon() - time.sleep(2) if __name__ == '__main__': dtest.run() diff --git a/tests/version.py b/tests/version.py index dbb0df6..9ec922c 100755 --- a/tests/version.py +++ b/tests/version.py @@ -23,7 +23,6 @@ import dtest,time,disorder def test(): """Ask the server its version number""" dtest.start_daemon() - time.sleep(2) # give the daemon a chance to start up c = disorder.client() v = c.version() print "Server version: %s" % v -- [mdw]