aboutsummaryrefslogtreecommitdiff
path: root/ChangeLog
diff options
context:
space:
mode:
Diffstat (limited to 'ChangeLog')
0 files changed, 0 insertions, 0 deletions
elease those locks that we have already acquired. */ /* Sort the paths. This assures that locks are always acquired in the same order, thus preventing deadlocks. */ Paths paths(_paths.begin(), _paths.end()); paths.sort(); /* Acquire the lock for each path. */ foreach (Paths::iterator, i, paths) { checkInterrupt(); Path path = *i; Path lockPath = path + ".lock"; debug(format("locking path `%1%'") % path); if (lockedPaths.find(lockPath) != lockedPaths.end()) throw Error("deadlock: trying to re-acquire self-held lock"); AutoCloseFD fd; while (1) { /* Open/create the lock file. */ fd = openLockFile(lockPath, true); /* Acquire an exclusive lock. */ if (!lockFile(fd, ltWrite, false)) { if (wait) { if (waitMsg != "") printMsg(lvlError, waitMsg); lockFile(fd, ltWrite, true); } else { /* Failed to lock this path; release all other locks. */ unlock(); return false; } } debug(format("lock acquired on `%1%'") % lockPath); /* Check that the lock file hasn't become stale (i.e., hasn't been unlinked). */ struct stat st; if (fstat(fd, &st) == -1) throw SysError(format("statting lock file `%1%'") % lockPath); if (st.st_size != 0) /* This lock file has been unlinked, so we're holding a lock on a deleted file. This means that other processes may create and acquire a lock on `lockPath', and proceed. So we must retry. */ debug(format("open lock file `%1%' has become stale") % lockPath); else break; } /* Use borrow so that the descriptor isn't closed. */ fds.push_back(FDPair(fd.borrow(), lockPath)); lockedPaths.insert(lockPath); } return true; } PathLocks::~PathLocks() { try { unlock(); } catch (...) { ignoreException(); } } void PathLocks::unlock() { foreach (list<FDPair>::iterator, i, fds) { if (deletePaths) deleteLockFile(i->second, i->first); lockedPaths.erase(i->second); if (close(i->first) == -1) printMsg(lvlError, format("error (ignored): cannot close lock file on `%1%'") % i->second); debug(format("lock released on `%1%'") % i->second); } fds.clear(); } void PathLocks::setDeletion(bool deletePaths) { this->deletePaths = deletePaths; } bool pathIsLockedByMe(const Path & path) { Path lockPath = path + ".lock"; return lockedPaths.find(lockPath) != lockedPaths.end(); } }