chiark / gitweb /
The initial rescan now blocks any client connections. This means that
authorRichard Kettlewell <rjk@greenend.org.uk>
Thu, 22 Nov 2007 11:35:34 +0000 (11:35 +0000)
committerRichard Kettlewell <rjk@greenend.org.uk>
Thu, 22 Nov 2007 11:35:34 +0000 (11:35 +0000)
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).

The tests now take advantage of this by waiting until the socket
appears before assuming the daemon has started.

server/disorderd.c
server/trackdb.c
tests/alltests
tests/dtest.py
tests/nothing.py
tests/version.py

index e8e1046..758907c 100644 (file)
@@ -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);
index 8cfd71f..57ebb68 100644 (file)
@@ -34,6 +34,7 @@
 #include <sys/resource.h>
 #include <time.h>
 #include <arpa/inet.h>
+#include <sys/wait.h>
 
 #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) {
index b115f7d..812b53a 100755 (executable)
@@ -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
index 38c7219..6ae9fd7 100644 (file)
@@ -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):
index f3bdeb9..c12443e 100755 (executable)
@@ -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()
index dbb0df6..9ec922c 100755 (executable)
@@ -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