diff options
-rw-r--r-- | ChangeLog | 1 | ||||
-rw-r--r-- | lib/bb/fetch/__init__.py | 9 | ||||
-rw-r--r-- | lib/bb/utils.py | 37 |
3 files changed, 40 insertions, 7 deletions
@@ -78,6 +78,7 @@ Changes in Bitbake 1.9.x: - Add BB_GENERATE_MIRROR_TARBALLS option, set to 0 to make git fetches faster at the expense of not creating mirror tarballs. - SRCREV handling updates, improvements and fixes from Poky + - Add bb.utils.lockfile() and bb.utils.unlockfile() from Poky Changes in Bitbake 1.8.0: - Release 1.7.x as a stable series diff --git a/lib/bb/fetch/__init__.py b/lib/bb/fetch/__init__.py index 4da92110e..d75c618de 100644 --- a/lib/bb/fetch/__init__.py +++ b/lib/bb/fetch/__init__.py @@ -141,21 +141,18 @@ def go(d): # Touch md5 file to show activity os.utime(ud.md5, None) continue - lf = open(ud.lockfile, "a+") - fcntl.flock(lf.fileno(), fcntl.LOCK_EX) + lf = bb.utils.lockfile(ud.lockfile) if not m.forcefetch(u, ud, d) and os.path.exists(ud.md5): # If someone else fetched this before we got the lock, # notice and don't try again os.utime(ud.md5, None) - fcntl.flock(lf.fileno(), fcntl.LOCK_UN) - lf.close + bb.utils.unlockfile(lf) continue m.go(u, ud, d) if ud.localfile: if not m.forcefetch(u, ud, d): Fetch.write_md5sum(u, ud, d) - fcntl.flock(lf.fileno(), fcntl.LOCK_UN) - lf.close + bb.utils.unlockfile(lf) def localpaths(d): """ diff --git a/lib/bb/utils.py b/lib/bb/utils.py index c2884f263..c27dafd61 100644 --- a/lib/bb/utils.py +++ b/lib/bb/utils.py @@ -22,7 +22,7 @@ BitBake Utility Functions digits = "0123456789" ascii_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" -import re +import re, fcntl, os def explode_version(s): r = [] @@ -202,3 +202,38 @@ def Enum(*names): constants = tuple(constants) EnumType = EnumClass() return EnumType + +def lockfile(name): + """ + Use the file fn as a lock file, return when the lock has been aquired. + Returns a variable to pass to unlockfile(). + """ + while True: + # If we leave the lockfiles lying around there is no problem + # but we should clean up after ourselves. This gives potential + # for races though. To work around this, when we aquire the lock + # we check the file we locked was still the lock file on disk. + # by comparing inode numbers. If they don't match or the lockfile + # no longer exists, we start again. + + # This implementation is unfair since the last person to request the + # lock is the most likely to win it. + + lf = open(name, "a+") + fcntl.flock(lf.fileno(), fcntl.LOCK_EX) + statinfo = os.fstat(lf.fileno()) + if os.path.exists(lf.name): + statinfo2 = os.stat(lf.name) + if statinfo.st_ino == statinfo2.st_ino: + return lf + # File no longer exists or changed, retry + lf.close + +def unlockfile(lf): + """ + Unlock a file locked using lockfile() + """ + os.unlink(lf.name) + fcntl.flock(lf.fileno(), fcntl.LOCK_UN) + lf.close + |