Package: reprepro Version: 4.14.0-1 Severity: normal Tags: patch When reprepro crashes, the database lock file is not released, because the lock file still exists on the system. A patch is attached that changes the locking system to use fcntl() to lock the database lockfile instead of open with O_EXCL. With this change, the lock is correctly released in case of the reprepro process is crashing.
>From 31c4cb8fa6ecddc164e5fe2f51a91360f4fa402d Mon Sep 17 00:00:00 2001 From: Benjamin Drung <benjamin.dr...@profitbricks.com> Date: Wed, 11 Jun 2014 17:49:59 +0200 Subject: Use fcntl() to lock the database lockfile instead of open with O_EXCL.
The lock required with fcntl() is correctly released in case of the reprepro process is crashing. Signed-off-by: Benjamin Drung <benjamin.dr...@profitbricks.com> --- database.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/database.c b/database.c index c6111be..6805b23 100644 --- a/database.c +++ b/database.c @@ -90,9 +90,11 @@ static inline char *dbfilename(const char *filename) { static retvalue database_lock(size_t waitforlock) { char *lockfile; + int e; int fd; retvalue r; size_t tries = 0; + struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, getpid()}; assert (!rdb_locked); rdb_dircreationdepth = 0; @@ -103,23 +105,29 @@ static retvalue database_lock(size_t waitforlock) { lockfile = dbfilename("lockfile"); if (FAILEDTOALLOC(lockfile)) return RET_ERROR_OOM; - fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY, + fd = open(lockfile, O_WRONLY|O_CREAT|O_NOFOLLOW|O_NOCTTY, S_IRUSR|S_IWUSR); - while (fd < 0) { - int e = errno; - if (e == EEXIST) { + if (fd == -1) { + e = errno; + fprintf(stderr, +"Error %d creating lock file '%s': %s!\n", + e, lockfile, strerror(e)); + free(lockfile); + return RET_ERRNO(e); + } + while (fcntl(fd, F_SETLK, &fl) < 0) { + e = errno; + if (e == EACCES || e == EAGAIN) { if (tries < waitforlock && ! interrupted()) { unsigned int timetosleep = 10; if (verbose >= 0) printf( -"Could not aquire lock: %s already exists!\nWaiting 10 seconds before trying again.\n", - lockfile); - while (timetosleep > 0) +"Could not aquire lock: %s is already locked by process %i!\nWaiting %i seconds before trying again.\n", + lockfile, fl.l_pid, timetosleep); + while (timetosleep > 0) { timetosleep = sleep(timetosleep); + } tries++; - fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL - |O_NOFOLLOW|O_NOCTTY, - S_IRUSR|S_IWUSR); continue; } @@ -131,22 +139,11 @@ static retvalue database_lock(size_t waitforlock) { } else fprintf(stderr, -"Error %d creating lock file '%s': %s!\n", +"Error %d locking lock file '%s': %s!\n", e, lockfile, strerror(e)); free(lockfile); return RET_ERRNO(e); } - // TODO: do some more locking of this file to avoid problems - // with the non-atomity of O_EXCL with nfs-filesystems... - if (close(fd) != 0) { - int e = errno; - fprintf(stderr, -"(Late) Error %d creating lock file '%s': %s!\n", - e, lockfile, strerror(e)); - (void)unlink(lockfile); - free(lockfile); - return RET_ERRNO(e); - } free(lockfile); rdb_locked = true; return RET_OK; -- 1.9.1