abuild-fetch: try to work around an ESTALE error which occurs on NFS

This is because of the following race condition case:

  A                               B
                                |
  lockfd = open(lockfile, ...)  |
                                | unlink(lockfile)
  lockf(lockfd, F_LOCK, 0)      |

According to [1], to recover from an ESTALE error, an application must
close the file or directory where the error occurred, and reopen it so
the NFS client can resolve the pathname again and retrieve the new file
handle.

[1] https://nfs.sourceforge.net/#faq_a10
This commit is contained in:
Dmitry Klochkov 2024-05-21 03:36:07 +03:00 committed by Natanael Copa
parent 2fbfb5e700
commit 15b9496135

View File

@ -81,11 +81,22 @@ int fork_exec(char *argv[], int showerr)
static int acquire_lock(const char *lockfile)
{
int lockfd = open(lockfile, O_WRONLY|O_CREAT, 0660);
if (lockfd < 0)
err(1, "%s", lockfile);
int lockfd, i, r;
if (lockf(lockfd, F_LOCK, 0) == -1)
/* try to work around an ESTALE error which occurs on NFS */
for (i = 0; i < 10; i++, sleep(1)) {
lockfd = open(lockfile, O_WRONLY|O_CREAT, 0660);
if (lockfd < 0)
err(1, "%s", lockfile);
r = lockf(lockfd, F_LOCK, 0);
if (r == 0 || errno != ESTALE)
break;
close(lockfd);
}
if (r != 0)
err(1, "failed to acquire lock: %s", lockfile);
return lockfd;