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.
/* ignore SIGPIPE */
signal(SIGPIPE, SIG_IGN);
/* start a rescan straight away */
/* 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);
rescan_after(86400);
/* periodically tidy up the database */
dbgc_after(60);
#include <sys/resource.h>
#include <time.h>
#include <arpa/inet.h>
#include <sys/resource.h>
#include <time.h>
#include <arpa/inet.h>
#include "event.h"
#include "mem.h"
#include "event.h"
#include "mem.h"
}
void trackdb_rescan(ev_source *ev) {
}
void trackdb_rescan(ev_source *ev) {
if(rescan_pid != -1) {
error(0, "rescan already underway");
return;
}
rescan_pid = subprogram(ev, RESCAN, -1);
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) {
}
int trackdb_rescan_cancel(void) {
tests.sort() # let's have a consistent order
for test in tests:
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
dtest.run(test, report=False)
print "%d tests" % dtest.tests
"""Utility module used by tests"""
"""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"""
def fatal(s):
"""Write an error message and exit"""
global daemon, errs
assert daemon == None
print " starting 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
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()
def stop_daemon():
"""stop_daemon()
if rc == None:
print " stopping daemon"
os.kill(daemon.pid, 15)
if rc == None:
print " stopping daemon"
os.kill(daemon.pid, 15)
+ print " waiting for daemon"
- print " daemon has stopped"
+ print " daemon has stopped"
+ else:
+ print " daemon already stopped"
daemon = None
def run(module=None, report=True):
daemon = None
def run(module=None, report=True):
import dtest,time
def test():
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"""
if __name__ == '__main__':
dtest.run()
if __name__ == '__main__':
dtest.run()
def test():
"""Ask the server its version number"""
dtest.start_daemon()
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
c = disorder.client()
v = c.version()
print "Server version: %s" % v