[pacman-dev] FS#9424 : storing pid in db.lck
Quote from the feature request :
Pacman would be able to handle automatically lock file removal without user interaction if db.lck was dead, but it would still be locked if it was alive.
That looks interesting, and there is also a patch attached, that I am repasting here: diff -Naur pacman-3.1.1/lib/libalpm/alpm.h pacman-3.1.1.bak/lib/libalpm/alpm.h --- pacman-3.1.1/lib/libalpm/alpm.h 2008-01-20 20:14:45.000000000 +0100 +++ pacman-3.1.1.bak/lib/libalpm/alpm.h 2008-02-03 03:58:03.000000000 +0100 @@ -428,6 +428,7 @@ PM_ERR_HANDLE_NULL, PM_ERR_HANDLE_NOT_NULL, PM_ERR_HANDLE_LOCK, + PM_ERR_INSTANCE_RUNNING, /* Databases */ PM_ERR_DB_OPEN, PM_ERR_DB_CREATE, diff -Naur pacman-3.1.1/lib/libalpm/error.c pacman-3.1.1.bak/lib/libalpm/error.c --- pacman-3.1.1/lib/libalpm/error.c 2008-01-20 20:14:45.000000000 +0100 +++ pacman-3.1.1.bak/lib/libalpm/error.c 2008-02-03 03:58:03.000000000 +0100 @@ -56,6 +56,8 @@ return _("library already initialized"); case PM_ERR_HANDLE_LOCK: return _("unable to lock database"); + case PM_ERR_INSTANCE_RUNNING: + return _("another instance is running"); /* Databases */ case PM_ERR_DB_OPEN: return _("could not open database"); diff -Naur pacman-3.1.1/lib/libalpm/trans.c pacman-3.1.1.bak/lib/libalpm/trans.c --- pacman-3.1.1/lib/libalpm/trans.c 2008-01-20 20:17:05.000000000 +0100 +++ pacman-3.1.1.bak/lib/libalpm/trans.c 2008-02-03 03:58:03.000000000 +0100 @@ -75,6 +75,8 @@ handle->lckfd = _alpm_lckmk(); if(handle->lckfd == -1) { RET_ERR(PM_ERR_HANDLE_LOCK, -1); + } else if(handle->lckfd == -2) { + RET_ERR(PM_ERR_INSTANCE_RUNNING, -1); } handle->trans = _alpm_trans_new(); diff -Naur pacman-3.1.1/lib/libalpm/util.c pacman-3.1.1.bak/lib/libalpm/util.c --- pacman-3.1.1/lib/libalpm/util.c 2008-01-20 20:17:05.000000000 +0100 +++ pacman-3.1.1.bak/lib/libalpm/util.c 2008-02-03 17:49:53.000000000 +0100 @@ -330,30 +330,64 @@ return newstr; } - /* Create a lock file */ int _alpm_lckmk() { - int fd, count = 0; + /* + * pid: string representing pacman pid + * tmpfile: string containing the temporary file + * sizeofpid: integer that stores sizeof(pid) + */ + char pid[7], tmpfile[19]="/tmp/pacman-lock-", existingpid[7], runningprocess[15]="/proc/"; + int fd, count, sizeofpid; char *dir, *ptr; - const char *file = alpm_option_get_lockfile(); - + struct stat st; + const char *lockfile = alpm_option_get_lockfile(); + /* create the dir of the lockfile first */ - dir = strdup(file); + dir = strdup(lockfile); ptr = strrchr(dir, '/'); if(ptr) { *ptr = '\0'; } _alpm_makepath(dir); + + // fill with zeroes + for (count=0; count<sizeof(existingpid); count++) { + existingpid[count]='\0'; + } - while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -1 && errno == EACCES) { + /* check if there is another lock, and if so, check if its associated process is running */ + if ((fd = open(lockfile, O_RDONLY , 0000)) != -1) { + read(fd, existingpid, sizeof(existingpid)); + int n = read(fd, existingpid, sizeof(existingpid)); + close(fd); + existingpid[n] = '\0'; + strcat(runningprocess,existingpid); + if (stat(runningprocess, &st) != -1 && S_ISDIR(st.st_mode)) { + return -2; + } + } + if (unlink(lockfile) == -1 && errno != ENOENT) { + return -1; + } + + sizeofpid = sprintf(pid, "%d", getpid()); + strcat(tmpfile,pid); + + count=0; + while((fd = open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0444)) == -1 && errno == EACCES) { if(++count < 1) { sleep(1); - } else { + } else { return(-1); } } + write(fd, pid, sizeofpid); + + symlink(tmpfile, lockfile); + FREE(dir); return(fd > 0 ? fd : -1); @@ -362,13 +396,23 @@ /* Remove a lock file */ int _alpm_lckrm() { - const char *file = alpm_option_get_lockfile(); - if(unlink(file) == -1 && errno != ENOENT) { + char pid[7], tmpfile[19]="/tmp/pacman-lock-"; + const char *lockfile = alpm_option_get_lockfile(); + int unlinkstatus=0; + + sprintf(pid, "%d", getpid()); + strcat(tmpfile,pid); + + if(unlink(tmpfile) == -1 && errno != ENOENT) { + unlinkstatus=-1; + } + if(unlink(lockfile) == -1 && errno != ENOENT) { return(-1); } - return(0); + return (unlinkstatus); } + /* Compression functions */ int _alpm_unpack(const char *archive, const char *prefix, const char *fn)
Quote from the feature request :
Pacman would be able to handle automatically lock file removal without user interaction if db.lck was dead, but it would still be locked if it was alive.
That looks interesting, and there is also a patch attached, that I am repasting here:
diff -Naur pacman-3.1.1/lib/libalpm/alpm.h pacman-3.1.1.bak/lib/libalpm/alpm.h --- pacman-3.1.1/lib/libalpm/alpm.h 2008-01-20 20:14:45.000000000 +0100 +++ pacman-3.1.1.bak/lib/libalpm/alpm.h 2008-02-03 03:58:03.000000000 +0100 @@ -428,6 +428,7 @@ PM_ERR_HANDLE_NULL, PM_ERR_HANDLE_NOT_NULL, PM_ERR_HANDLE_LOCK, + PM_ERR_INSTANCE_RUNNING, /* Databases */ PM_ERR_DB_OPEN, PM_ERR_DB_CREATE, diff -Naur pacman-3.1.1/lib/libalpm/error.c pacman-3.1.1.bak/lib/libalpm/error.c --- pacman-3.1.1/lib/libalpm/error.c 2008-01-20 20:14:45.000000000 +0100 +++ pacman-3.1.1.bak/lib/libalpm/error.c 2008-02-03 03:58:03.000000000 +0100 @@ -56,6 +56,8 @@ return _("library already initialized"); case PM_ERR_HANDLE_LOCK: return _("unable to lock database"); + case PM_ERR_INSTANCE_RUNNING: + return _("another instance is running"); /* Databases */ case PM_ERR_DB_OPEN: return _("could not open database"); diff -Naur pacman-3.1.1/lib/libalpm/trans.c pacman-3.1.1.bak/lib/libalpm/trans.c --- pacman-3.1.1/lib/libalpm/trans.c 2008-01-20 20:17:05.000000000 +0100 +++ pacman-3.1.1.bak/lib/libalpm/trans.c 2008-02-03 03:58:03.000000000 +0100 @@ -75,6 +75,8 @@ handle->lckfd = _alpm_lckmk(); if(handle->lckfd == -1) { RET_ERR(PM_ERR_HANDLE_LOCK, -1); + } else if(handle->lckfd == -2) { + RET_ERR(PM_ERR_INSTANCE_RUNNING, -1); }
handle->trans = _alpm_trans_new(); diff -Naur pacman-3.1.1/lib/libalpm/util.c pacman-3.1.1.bak/lib/libalpm/util.c --- pacman-3.1.1/lib/libalpm/util.c 2008-01-20 20:17:05.000000000 +0100 +++ pacman-3.1.1.bak/lib/libalpm/util.c 2008-02-03 17:49:53.000000000 +0100 @@ -330,30 +330,64 @@ return newstr; }
- /* Create a lock file */ int _alpm_lckmk() { - int fd, count = 0; + /* + * pid: string representing pacman pid + * tmpfile: string containing the temporary file + * sizeofpid: integer that stores sizeof(pid) + */ + char pid[7], tmpfile[19]="/tmp/pacman-lock-", existingpid[7], runningprocess[15]="/proc/"; + int fd, count, sizeofpid; char *dir, *ptr; - const char *file = alpm_option_get_lockfile(); - + struct stat st; + const char *lockfile = alpm_option_get_lockfile(); + /* create the dir of the lockfile first */ - dir = strdup(file); + dir = strdup(lockfile); ptr = strrchr(dir, '/'); if(ptr) { *ptr = '\0'; } _alpm_makepath(dir); + + // fill with zeroes + for (count=0; count<sizeof(existingpid); count++) { + existingpid[count]='\0'; + }
- while((fd = open(file, O_WRONLY | O_CREAT | O_EXCL, 0000)) == -1 && errno == EACCES) { + /* check if there is another lock, and if so, check if its associated process is running */ + if ((fd = open(lockfile, O_RDONLY , 0000)) != -1) { + read(fd, existingpid, sizeof(existingpid)); + int n = read(fd, existingpid, sizeof(existingpid)); + close(fd); + existingpid[n] = '\0'; + strcat(runningprocess,existingpid); + if (stat(runningprocess, &st) != -1 && S_ISDIR(st.st_mode)) { + return -2; + } + } + if (unlink(lockfile) == -1 && errno != ENOENT) { + return -1; + } + + sizeofpid = sprintf(pid, "%d", getpid()); + strcat(tmpfile,pid); + + count=0; + while((fd = open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0444)) == -1 && errno == EACCES) { if(++count < 1) { sleep(1); - } else { + } else { return(-1); } }
+ write(fd, pid, sizeofpid); + + symlink(tmpfile, lockfile); + FREE(dir);
return(fd > 0 ? fd : -1); @@ -362,13 +396,23 @@ /* Remove a lock file */ int _alpm_lckrm() { - const char *file = alpm_option_get_lockfile(); - if(unlink(file) == -1 && errno != ENOENT) { + char pid[7], tmpfile[19]="/tmp/pacman-lock-"; + const char *lockfile = alpm_option_get_lockfile(); + int unlinkstatus=0; + + sprintf(pid, "%d", getpid()); + strcat(tmpfile,pid); + + if(unlink(tmpfile) == -1 && errno != ENOENT) { + unlinkstatus=-1; + } + if(unlink(lockfile) == -1 && errno != ENOENT) { return(-1); } - return(0); + return (unlinkstatus); }
+ /* Compression functions */
int _alpm_unpack(const char *archive, const char *prefix, const char *fn)
_______________________________________________ pacman-dev mailing list pacman-dev@archlinux.org http://archlinux.org/mailman/listinfo/pacman-dev
Hi! 1. I don't really understand why this /tmp/* stuff is needed (and tmpfile shouldn't be PACMAN specific). We could write the pid to the lockfile directly. 2. Just for safety we could compare our current pid and the lock-pid on lockfile removal. Bye ---------------------------------------------------- SZTE Egyetemi Könyvtár - http://www.bibl.u-szeged.hu This mail sent through IMP: http://horde.org/imp/
On Tue, Feb 19, 2008 at 05:26:00PM +0100, Nagy Gabor wrote:
Hi! 1. I don't really understand why this /tmp/* stuff is needed (and tmpfile shouldn't be PACMAN specific). We could write the pid to the lockfile directly.
There is an explanation in the comments : "Also, I was wondering why good locking systems create symlinks to temporary files. I found why: the pid that pacman had when the db.lck file was created can be assigned to another process after a reboot, so the workaround for this is to create db.lck in /tmp and symlink it to /var/lib/pacman. This way nonroot users still can't lock pacman db, but after a reboot the lock file is gone."
2. Just for safety we could compare our current pid and the lock-pid on lockfile removal.
Maybe (patches always welcome :)).
participants (2)
-
Nagy Gabor
-
Xavier