mirror of
https://gitlab.alpinelinux.org/alpine/abuild.git
synced 2024-12-25 00:12:19 +00:00
abuild-fetch: simplify and fix locking
Simplify locking by using lockf(3). It is POSIX compatible and should
work over NFS.
Fix download race condition when:
1) host A creates lockfile and aquire lock to fetch from distfiles
mirror
2) host B opens the lockfile and waits for lock
3) host A gets 404 from distfiles, releases lock and deletes the
lockfile, which host A has an open file handle for
4) host B gets lock of the deleted file and downloads file
5) host A retries download and creates a new lockfile, but is not
blocked by host B, even if it should
Solve this by releaseing the lock, give the other processes a chance
to aquire it (using sleep(0)), and then only delete the lockfile if:
a) download was successful (no 404) or b) no-one else has a lock.
This reverts commit 281720ec39
(abuild-fetch: aquire a second lock
using flock(2))
fixes #10026
This commit is contained in:
parent
6a6145b9b3
commit
3da770ce35
@ -80,45 +80,26 @@ int fork_exec(char *argv[], int showerr)
|
|||||||
|
|
||||||
static int aquire_lock(const char *lockfile)
|
static int aquire_lock(const char *lockfile)
|
||||||
{
|
{
|
||||||
struct flock fl = {
|
|
||||||
.l_type = F_WRLCK,
|
|
||||||
.l_whence = SEEK_SET,
|
|
||||||
.l_start = 1,
|
|
||||||
.l_len = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
int lockfd = open(lockfile, O_WRONLY|O_CREAT, 0660);
|
int lockfd = open(lockfile, O_WRONLY|O_CREAT, 0660);
|
||||||
if (lockfd < 0)
|
if (lockfd < 0)
|
||||||
err(1, "%s", lockfile);
|
err(1, "%s", lockfile);
|
||||||
|
|
||||||
/* create NFS-safe lock */
|
if (lockf(lockfd, F_LOCK, 0) == -1)
|
||||||
if (fcntl(lockfd, F_SETLK, &fl) < 0) {
|
err(1, "failed to aquire lock: %s", lockfile);
|
||||||
int i;
|
|
||||||
printf("Waiting for %s ...\n", lockfile);
|
|
||||||
for (i=0; i<10; i++) {
|
|
||||||
int r = fcntl(lockfd, F_SETLKW, &fl);
|
|
||||||
if (r == 0)
|
|
||||||
break;
|
|
||||||
if (r == -1 && errno != ESTALE)
|
|
||||||
err(1, "fcntl(F_SETLKW)");
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int r = flock(lockfd, LOCK_EX);
|
|
||||||
if (r == -1)
|
|
||||||
err(1, "flock: %s", lockfile);
|
|
||||||
|
|
||||||
return lockfd;
|
return lockfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void release_lock(int lockfd)
|
static void release_lock(int lockfd)
|
||||||
{
|
{
|
||||||
int r = flock(lockfd, LOCK_UN);
|
if (lockf(lockfd, F_ULOCK, 0) == -1)
|
||||||
if (r == -1)
|
err(1, "failed to release lock");
|
||||||
err(1, "flock");
|
|
||||||
|
|
||||||
close(lockfd);
|
}
|
||||||
|
|
||||||
|
static int try_lock(int lockfd)
|
||||||
|
{
|
||||||
|
return lockf(lockfd, F_TLOCK, 0) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create or wait for an NFS-safe lockfile and fetch url with curl or wget */
|
/* create or wait for an NFS-safe lockfile and fetch url with curl or wget */
|
||||||
@ -197,9 +178,14 @@ int fetch(char *url, const char *destdir, bool insecure)
|
|||||||
rename(partfile, outfile);
|
rename(partfile, outfile);
|
||||||
|
|
||||||
fetch_done:
|
fetch_done:
|
||||||
unlink(lockfile);
|
|
||||||
release_lock(lockfd);
|
release_lock(lockfd);
|
||||||
lockfile[0] = '\0';
|
|
||||||
|
// give other processes the chance to aquire the lock if they have the file open
|
||||||
|
sleep(0);
|
||||||
|
|
||||||
|
if (status == 0 || try_lock(lockfd))
|
||||||
|
unlink(lockfile);
|
||||||
|
close(lockfd);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user