1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 import os
17 import sys
18 import fcntl
19 from errno import EWOULDBLOCK, EEXIST
20 from rhn.i18n import bstr
21 import fcntl
22
24 """thrown ONLY when pid file is locked."""
25 pass
26
28
29 """class that provides simple access to a PID-style lockfile.
30
31 methods: __init__(lockfile), acquire(), and release()
32 NOTE: currently acquires upon init
33 The *.pid file will be acquired, or an LockfileLockedException is raised.
34 """
35
37 """create (if need be), and acquire lock on lockfile
38
39 lockfile example: '/var/run/up2date.pid'
40 """
41
42
43 self.lockfile = os.path.abspath(
44 os.path.expanduser(
45 os.path.expandvars(lockfile)))
46
47 self.pid = pid
48 if not self.pid:
49 self.pid = os.getpid()
50
51
52 dirname = os.path.dirname(self.lockfile)
53 if not os.path.exists(dirname):
54 try:
55 os.makedirs(dirname)
56 except OSError:
57 e = sys.exc_info()[1]
58 if hasattr(e, 'errno') and e.errno == EEXIST:
59
60 pass
61 else:
62 raise
63
64
65
66 self.f = os.open(self.lockfile, os.O_RDWR|os.O_CREAT|os.O_SYNC)
67 self.acquire()
68
70 """acquire the lock; else raise LockfileLockedException."""
71
72 try:
73 fcntl.flock(self.f, fcntl.LOCK_EX|fcntl.LOCK_NB)
74 except IOError:
75 if sys.exc_info()[1].errno == EWOULDBLOCK:
76 raise LockfileLockedException(
77 "cannot acquire lock on %s." % self.lockfile, None, sys.exc_info()[2])
78 else:
79 raise
80
81 fcntl.fcntl(self.f, fcntl.F_SETFD, 1)
82
83 os.ftruncate(self.f, 0)
84 os.write(self.f, bstr(str(self.pid) + '\n'))
85
87
88 os.unlink(self.lockfile)
89 fcntl.flock(self.f, fcntl.LOCK_UN)
90 os.close(self.f)
91
92
94 """test code"""
95
96 try:
97 L = Lockfile('./test.pid')
98 except LockfileLockedException:
99 sys.stderr.write("%s\n" % sys.exc_info()[1])
100 sys.exit(-1)
101 else:
102 print("lock acquired ")
103 print("...sleeping for 10 seconds")
104 import time
105 time.sleep(10)
106 L.release()
107 print("lock released ")
108
109 if __name__ == '__main__':
110
111 sys.exit(main() or 0)
112