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