From 35474657bdff7b708d3c8812be6386e25383095c Mon Sep 17 00:00:00 2001 From: Julien Jehannet Date: Tue, 20 Jan 2009 12:46:13 +0100 Subject: use UserWarning instead of poor print statement --- shellutils.py | 30 +++++++++++++++++++++--------- test/unittest_shellutils.py | 16 +++++++++++++++- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/shellutils.py b/shellutils.py index d964705..337a9dc 100644 --- a/shellutils.py +++ b/shellutils.py @@ -11,6 +11,7 @@ __docformat__ = "restructuredtext en" import os import glob import shutil +import stat import sys import tempfile import time @@ -201,8 +202,13 @@ class Execute: os.remove(outfile) os.remove(errfile) -def acquire_lock(lock_file, max_try=10, delay=10): - """Acquire a lock represented by a file on the file system.""" +def acquire_lock(lock_file, max_try=10, delay=10, max_delay=3600): + """Acquire a lock represented by a file on the file system + + If the process written in lock file doesn't exist anymore, we remove the + lock file immediately + If age of the lock_file is greater than max_delay, then we raise a UserWarning + """ count = abs(max_try) while count: try: @@ -216,14 +222,20 @@ def acquire_lock(lock_file, max_try=10, delay=10): fd = open(lock_file, "r") pid = int(fd.readline()) pi = ProcInfo(pid) - # only print the message one time - if count == max_try: - diff = (int(time.time()) - pi.age()) / 60 - print("Command '%s' (pid %s) has locked the file '%s' for %s minutes.\nWaiting..." % (pi.name(), pid, lock_file, diff)) + age = (time.time() - os.stat(lock_file)[stat.ST_MTIME]) + if age / max_delay > 1 : + raise UserWarning("Command '%s' (pid %s) has locked the " + "file '%s' for %s minutes" + % (pi.name(), pid, lock_file, age/60)) + except UserWarning: + raise except NoSuchProcess: - raise NoSuchProcess('You can delete the lock file "%s" safely' % lock_file) - except: - # process information are not accessible + os.remove(lock_file) + except Exception: + # The try block is not essential. can be skipped. + # Note: ProcInfo object is only available for linux + # process information are not accessible... + # or lock_file is no more present... pass else: raise diff --git a/test/unittest_shellutils.py b/test/unittest_shellutils.py index 903312d..17bc0e0 100644 --- a/test/unittest_shellutils.py +++ b/test/unittest_shellutils.py @@ -2,6 +2,7 @@ import sys, os, tempfile, shutil from os.path import join +import datetime, time from logilab.common.testlib import TestCase, unittest_main @@ -147,7 +148,20 @@ class AcquireLockTC(TestCase): os.write(fd, '1111111111') os.close(fd) self.assertTrue(os.path.exists(self.lock)) - self.assertRaises(NoSuchProcess, acquire_lock, self.lock) + self.assertRaises(Exception, acquire_lock, self.lock, 1, 1) + + def test_wrong_process_and_continue(self): + fd = os.open(self.lock, os.O_EXCL | os.O_RDWR | os.O_CREAT) + os.write(fd, '1111111111') + os.close(fd) + self.assertTrue(os.path.exists(self.lock)) + self.assertTrue(acquire_lock(self.lock)) + + def test_locked_for_one_hour(self): + self.assertTrue(acquire_lock(self.lock)) + touch = datetime.datetime.fromtimestamp(time.time() - 3601).strftime("%m%d%H%M") + os.system("touch -t %s %s" % (touch, self.lock)) + self.assertRaises(UserWarning, acquire_lock, self.lock, max_try=2, delay=1) if __name__ == '__main__': -- cgit v1.2.1