comparison pylons_app/lib/pidlock.py @ 506:d5efb83590ef

fixed lock decorator bug which didn't release the lock after func execution and rewrote the pidlock a little with Ask Solem suggestions! added tredning languages stats
author Marcin Kuzminski <marcin@python-works.com>
date Mon, 27 Sep 2010 02:17:03 +0200
parents d280aa1c85c6
children b50e79b4257a
comparison
equal deleted inserted replaced
505:5aba7adff196 506:d5efb83590ef
1 import os, time 1 import os, time
2 import sys 2 import sys
3 from warnings import warn 3 from warnings import warn
4 from multiprocessing.util import Finalize
5 import errno
4 6
5 class LockHeld(Exception):pass 7 class LockHeld(Exception):pass
6 8
7 9
8 class DaemonLock(object): 10 class DaemonLock(object):
25 self.desc = desc 27 self.desc = desc
26 self.debug = debug 28 self.debug = debug
27 self.held = False 29 self.held = False
28 #run the lock automatically ! 30 #run the lock automatically !
29 self.lock() 31 self.lock()
32 self._finalize = Finalize(self, DaemonLock._on_finalize,
33 args=(self, debug), exitpriority=10)
30 34
31 def __del__(self): 35 @staticmethod
32 if self.held: 36 def _on_finalize(lock, debug):
33 37 if lock.held:
34 # warn("use lock.release instead of del lock", 38 if debug:
35 # category = DeprecationWarning, 39 print 'leck held finilazing and running lock.release()'
36 # stacklevel = 2) 40 lock.release()
37
38 # ensure the lock will be removed
39 self.release()
40 41
41 42
42 def lock(self): 43 def lock(self):
43 """locking function, if lock is present it will raise LockHeld exception 44 """locking function, if lock is present it will raise LockHeld exception
44 """ 45 """
45 lockname = '%s' % (os.getpid()) 46 lockname = '%s' % (os.getpid())
46 47 if self.debug:
48 print 'running lock'
47 self.trylock() 49 self.trylock()
48 self.makelock(lockname, self.pidfile) 50 self.makelock(lockname, self.pidfile)
49 return True 51 return True
50 52
51 def trylock(self): 53 def trylock(self):
52 running_pid = False 54 running_pid = False
55 if self.debug:
56 print 'checking for already running process'
53 try: 57 try:
54 pidfile = open(self.pidfile, "r") 58 pidfile = open(self.pidfile, "r")
55 pidfile.seek(0) 59 pidfile.seek(0)
56 running_pid = pidfile.readline() 60 running_pid = int(pidfile.readline())
61
62 pidfile.close()
63
57 if self.debug: 64 if self.debug:
58 print 'lock file present running_pid: %s, checking for execution'\ 65 print 'lock file present running_pid: %s, checking for execution'\
59 % running_pid 66 % running_pid
60 # Now we check the PID from lock file matches to the current 67 # Now we check the PID from lock file matches to the current
61 # process PID 68 # process PID
62 if running_pid: 69 if running_pid:
63 if os.path.exists("/proc/%s" % running_pid): 70 try:
64 print "You already have an instance of the program running" 71 os.kill(running_pid, 0)
65 print "It is running as process %s" % running_pid 72 except OSError, exc:
66 raise LockHeld 73 if exc.errno in (errno.ESRCH, errno.EPERM):
74 print "Lock File is there but the program is not running"
75 print "Removing lock file for the: %s" % running_pid
76 self.release()
77 raise
67 else: 78 else:
68 print "Lock File is there but the program is not running" 79 print "You already have an instance of the program running"
69 print "Removing lock file for the: %s" % running_pid 80 print "It is running as process %s" % running_pid
70 self.release() 81 raise LockHeld()
82
71 except IOError, e: 83 except IOError, e:
72 if e.errno != 2: 84 if e.errno != 2:
73 raise 85 raise
74 86
75
76 def release(self): 87 def release(self):
77 """releases the pid by removing the pidfile 88 """releases the pid by removing the pidfile
78 """ 89 """
90 if self.debug:
91 print 'trying to release the pidlock'
92
79 if self.callbackfn: 93 if self.callbackfn:
80 #execute callback function on release 94 #execute callback function on release
81 if self.debug: 95 if self.debug:
82 print 'executing callback function %s' % self.callbackfn 96 print 'executing callback function %s' % self.callbackfn
83 self.callbackfn() 97 self.callbackfn()