ATLAS Offline Software
Loading...
Searching...
No Matches
SingleAppInstance.py
Go to the documentation of this file.
1# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2
3
7
8import os
9import socket
10import time
11import fcntl
12
14 '''Class to handle creating and removing lockfiles'''
15
16 # custom exceptions
17
18 class FileLockAcquisitionError(Exception): pass
19 class FileLockReleaseError(Exception): pass
20
21 # convenience callables for formatting
22 addr = lambda self: '%d@%s' % (self.pid, self.host)
23 fddr = lambda self: '<%s %s>' % (self.path, self.addr())
24 pddr = lambda self, lock: '<%s %s@%s>' %\
25 (self.path, lock['pid'], lock['host'])
26
27 def __init__(self, path, debug=None, blocking = False):
28 self.pid = os.getpid()
29 self.host = socket.gethostname()
30 self.path = path
31 self.debug = debug # set this to get status messages
32 self.locked = False
33 self.lockfile = None
34 self.blocking = blocking
35
36 def acquire(self):
37 '''Acquire a lock, returning self if successful, False otherwise'''
38 if self.islocked():
39 if self.debug:
40 lock = self._readlock()
41 print('Previous lock detected: %s' % self.pddr(lock))
42 return False
43 try:
44 fd = os.open(self.path, os.O_RDWR | os.O_CREAT, 0o777)
45 fh = os.fdopen(fd, 'r+')
46 self.lockfile = fh
47 fh.seek(0)
48 try:
49 fcntlflag = fcntl.LOCK_EX
50 if not self.blocking:
51 fcntlflag |= fcntl.LOCK_NB
52 fcntl.lockf(fh, fcntlflag)
53 self.locked = True
54 except IOError:
55 print('Unable to acquire lock on %s: existing lock %s' % (self.path, fh.read()))
56 fh.close()
57 return False
58 fh.write(self.addr())
59 fh.truncate()
60 fh.flush()
61 os.fsync(fh)
62 if self.debug:
63 modtime = os.stat(self.path)
64 outstring = 'Acquired lock: '+ self.fddr() + ' at time '+ time.ctime(modtime.st_mtime)
65 print(outstring)
66 except Exception as e:
67 if os.path.isfile(self.path):
68 try:
69 # my guess is this causes problems
70 #os.unlink(self.path)
71 pass
72 except Exception:
73 pass
74 raise self.FileLockAcquisitionError(
75 'Error acquiring lock: %s, reason %s' % (self.fddr(), e))
76 return self
77
78 def release(self):
79 '''Release lock, returning self'''
80 if self.ownlock():
81 try:
82 fh = self.lockfile
83 fcntl.lockf(fh, fcntl.LOCK_UN)
84 self.locked = False
85 self.lockfile.close()
86 self.lockfile = None
87 if not self.blocking:
88 # some space for a small race here unfortunately
89 os.unlink(self.path)
90 if self.debug:
91 outstring = 'Released lock: ' + self.fddr() +' at time ' + time.ctime()
92 print(outstring)
93 except Exception as e:
94 print(e)
95 raise self.FileLockReleaseError(
96 'Error releasing lock: %s, reason %s' % (self.fddr(), e))
97 return self
98
99 def _readlock(self):
100 '''Internal method to read lock info'''
101 try:
102 lock = {}
103 fh = open(self.path)
104 data = fh.read().rstrip().split('@')
105 fh.close()
106 lock['pid'], lock['host'] = data
107 return lock
108 except Exception:
109 return {'pid': 8**10, 'host': ''}
110
111 def islocked(self):
112 '''Check if we already have a lock'''
113 return self.locked
114
115 def ownlock(self):
116 '''Check if we own the lock'''
117 return self.locked
118
119 def __del__(self):
120 '''Magic method to clean up lock when program exits'''
121 self.release()
122
123 def __enter__(self):
124 self.acquire()
125 return self
126
127 def __exit__(self, typ, value, tb):
128 self.release()
129 return self
void print(char *figname, TCanvas *c1)
__init__(self, path, debug=None, blocking=False)
static std::string release
Definition computils.h:50
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177