[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Dak proper locking



Hi all,

Here's a patch for Dak which implements proper locking by checking pids
etc.                                                               

Originally sent to Ganneff, but I know he's very busy at the mo.

I've checked and they're all working as expected on my local testbed,
but you may want to check your own too :) 
                                                                                                                                                                      
Neil
-- 
   __   
 .`  `. neilm@debian.org | Application Manager
 : :' ! ---------------- | Secure-Testing Team member
 '. `-  gpg: B345BDD3    | Webapps Team member
   `-   Please don't cc, I'm subscribed to the list
Index: jennifer
===================================================================
RCS file: /cvs/dak/dak/jennifer,v
retrieving revision 1.65
diff -u -r1.65 jennifer
--- jennifer	5 Dec 2005 05:35:47 -0000	1.65
+++ jennifer	17 Dec 2005 22:20:07 -0000
@@ -1305,20 +1305,14 @@
 
     # Check that we aren't going to clash with the daily cron job
 
-    if not Options["No-Action"] and os.path.exists("%s/daily.lock" % (Cnf["Dir::Lock"])) and not Options["No-Lock"]:
+    if not Options["No-Action"] and os.path.isfile("%s/daily.lock" % (Cnf["Dir::Lock"])) and not Options["No-Lock"]:
         utils.fubar("Archive maintenance in progress.  Try again later.");
 
     # Obtain lock if not in no-action mode and initialize the log
 
     if not Options["No-Action"]:
-        lock_fd = os.open(Cnf["Dinstall::LockFile"], os.O_RDWR | os.O_CREAT);
-        try:
-            fcntl.lockf(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB);
-        except IOError, e:
-            if errno.errorcode[e.errno] == 'EACCES' or errno.errorcode[e.errno] == 'EAGAIN':
-                utils.fubar("Couldn't obtain lock; assuming another jennifer is already running.");
-            else:
-                raise;
+        if not utils.lock_aquire(Cnf["Dinstall::LockFile"]):
+            utils.fubar("Couldn't obtain lock; assuming another jennifer is already running.");
         Logger = Katie.Logger = logging.Logger(Cnf, "jennifer");
 
     # debian-{devel-,}-changes@lists.debian.org toggles writes access based on this header
Index: kelly
===================================================================
RCS file: /cvs/dak/dak/kelly,v
retrieving revision 1.18
diff -u -r1.18 kelly
--- kelly	17 Dec 2005 10:57:03 -0000	1.18
+++ kelly	17 Dec 2005 22:20:07 -0000
@@ -607,14 +607,8 @@
 
     # Obtain lock if not in no-action mode and initialize the log
     if not Options["No-Action"]:
-        lock_fd = os.open(Cnf["Dinstall::LockFile"], os.O_RDWR | os.O_CREAT);
-        try:
-            fcntl.lockf(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB);
-        except IOError, e:
-            if errno.errorcode[e.errno] == 'EACCES' or errno.errorcode[e.errno] == 'EAGAIN':
-                utils.fubar("Couldn't obtain lock; assuming another kelly is already running.");
-            else:
-                raise;
+        if not utils.lock_aquire(Cnf["Dinstall::LockFile"]):
+            utils.fubar("Couldn't obtain lock; assuming another jennifer is already running.");
         Logger = Katie.Logger = logging.Logger(Cnf, "kelly");
         if not installing_to_stable and Cnf.get("Dir::UrgencyLog"):
             Urgency_Logger = Urgency_Log(Cnf);
Index: lisa
===================================================================
RCS file: /cvs/dak/dak/lisa,v
retrieving revision 1.31
diff -u -r1.31 lisa
--- lisa	15 Nov 2005 09:50:32 -0000	1.31
+++ lisa	17 Dec 2005 22:20:07 -0000
@@ -871,24 +871,18 @@
     print "ACCEPT";
     if not Options["No-Action"]:
         retry = 0;
-	while retry < 10:
-	    try:
-		lock_fd = os.open(Cnf["Lisa::AcceptedLockFile"], os.O_RDONLY | os.O_CREAT | os.O_EXCL);
-                retry = 10;
-	    except OSError, e:
-		if errno.errorcode[e.errno] == 'EACCES' or errno.errorcode[e.errno] == 'EEXIST':
+    while retry < 10:
+        if not utils.lock_aquire(Cnf["Lisa::AcceptedLockFile"]):
 		    retry += 1;
 		    if (retry >= 10):
 			utils.fubar("Couldn't obtain lock; assuming jennifer is already running.");
 		    else:
 			print("Unable to get accepted lock (try %d of 10)" % retry);
 		    time.sleep(60);
-		else:
-		    raise;
         (summary, short_summary) = Katie.build_summaries();
         Katie.accept(summary, short_summary);
         os.unlink(Katie.pkg.changes_file[:-8]+".katie");
-	os.unlink(Cnf["Lisa::AcceptedLockFile"]);
+        utils.lock_release(Cnf["Lisa::AcceptedLockFile"]);
 
 def check_status(files):
     new = byhand = 0;
Index: utils.py
===================================================================
RCS file: /cvs/dak/dak/utils.py,v
retrieving revision 1.73
diff -u -r1.73 utils.py
--- utils.py	18 Mar 2005 05:24:38 -0000	1.73
+++ utils.py	17 Dec 2005 22:20:07 -0000
@@ -1070,6 +1070,91 @@
     return filename;
 
 ################################################################################
+# Functions for dealing with lockfiles
+
+def lock_aquire(lockfile,pid=os.getpid()):
+    """Aquire a lockfile"""
+
+    __lock_makefile(lockfile);
+    # Permission check
+    if (lock_check(lockfile,pid) != 1):
+        warn("Coudn't obtain lock, in use by pid %s" % __lock_getpid(lockfile));
+        return 0;
+    else:
+        __lock_setpid(lockfile,pid);
+        return 1;
+
+def lock_release(lockfile,pid=os.getpid()):
+    """Release a lockfile. Checks permissions and won't release unless pid = the locked pid"""
+
+    # First, check if we have 'permission'
+    if (lock_check(lockfile,pid) != 1):
+        warn("Cannot release lockfile, no permission");
+        return 0;
+    else:
+        __lock_rmfile(lockfile);
+        return 1;
+        
+def lock_check(lockfile,pid=os.getpid()):
+    """Checks a lock against the given pid (or the current one)"""
+    pidset = __lock_getpid(lockfile);
+    if (pidset != 0 and pidset != "%s" % (pid) and pidset != ''):
+        try:
+            print(os.kill(int(pidset),0));
+        except OSError, err:
+            if (err.errno == 3):
+                # remove the stale lockfile
+                __lock_rmfile(lockfile);
+                return 1;
+        return 0;
+    return 1;
+     
+# Some private functions/methods/defs/whatever-python-calls-them
+def __lock_getpid(lockfile):
+    if os.path.isfile(lockfile) != True:
+        return 0;
+    else:
+        try:
+            fd = open(lockfile, "r");
+            pid = fd.readline();
+            pid = string.rstrip(pid);
+            fd.close();
+            return pid;
+        except IOError, err:
+            fubar("Couldn't retrieve pid from lockfile '%s'! : %s" % (filename,err.strerror));
+    
+def __lock_setpid(lockfile,pid):
+    if os.path.isfile(lockfile) != True:
+        __lock_makefile(lockfile);
+    try:
+        fd = open(lockfile, "w");
+        fd.write("%s" % pid);
+        fd.close();
+        return 1;
+    except IOError, err:
+        fubar("Coudn't write pid to the lockfile '%s'! : %s" % (filename,err.strerror));
+        
+def __lock_makefile(lockfile):
+    if os.path.isfile(lockfile):
+        return 0;
+    else:
+        try:
+            os.open(lockfile, os.O_CREAT, 0666);
+            return 1;
+        except IOError, err:
+            fubar("Coudn't create lockfile '%s': %s" % (filename,err.strerror));
+
+def __lock_rmfile(lockfile):
+    if os.path.isfile(lockfile):
+        try:
+            os.unlink(lockfile)
+            return 1;
+        except IOError, err:
+            fubar("Coudn't remove lockfile '%s': %s" % (filename,err.strerror));
+    else:
+        return 0;
+    
+################################################################################
 
 apt_pkg.init();
 

Attachment: signature.asc
Description: Digital signature


Reply to: