3

/var/lib/dpkg/lock is file that holding a lock when "A package manager is working". But how this system works? I have /var/lib/dpkg/lock everytime when I have Linux working. When I use one of package manager for dpkg I have it without any change. So I can't see it in action.

3 Answers 3

6

I don't know for certain, but this is most likely implemented via flock(). The flock() system call creates an advisory lock on a file. If another application tries to attain a lock on the file, the kernel will block until the original lock is gone, or return EWOULDBLOCK if the LOCK_NB option is given. This locking mechanism would allow the lock file to be used without deleting and re-creating it.

Update: Checked the source and verified that it is advisory locking, but it doesn't use flock() directly. fcntl is used:

enquiry.c:

        if (modstatdb_is_locked())
          puts(_(
"Another process has locked the database for writing, and might currently be\n"
"modifying it, some of the following problems might just be due to that.\n"));
        head_running = true;
      }

dbmodify.c:

modstatdb_is_locked(void)
{
  int lockfd;
  bool locked;

  if (dblockfd == -1) {
    lockfd = open(lockfile, O_RDONLY);
    if (lockfd == -1)
      ohshite(_("unable to open lock file %s for testing"), lockfile);
  } else {
    lockfd = dblockfd;
  }

  locked = file_is_locked(lockfd, lockfile);

  /* We only close the file if there was no lock open, otherwise we would
   * release the existing lock on close. */
  if (dblockfd == -1)
    close(lockfd);

  return locked;
}

file.c:

file_is_locked(int lockfd, const char *filename)
{
    struct flock fl;

    file_lock_setup(&fl, F_WRLCK);

    if (fcntl(lockfd, F_GETLK, &fl) == -1)
        ohshit(_("unable to check file '%s' lock status"), filename);

    if (fl.l_type == F_WRLCK && fl.l_pid != getpid())
        return true;
    else
        return false;
}

dpkg.h:

#define LOCKFILE          "lock"

From the fcntl manpage:

   Advisory locking
       F_GETLK,  F_SETLK  and  F_SETLKW  are  used to acquire, release, and test for the existence of record locks (also known as file-segment or file-region locks).  The third
       argument, lock, is a pointer to a structure that has at least the following fields (in unspecified order).
8
  • I tried this but it seems to not be the case. I manually grabbed an exclusive lock on the file, but dpkg still operated normally.
    – phemmer
    Apr 8, 2013 at 16:13
  • @Patrick I can see in the source code that it does in fact call flock() on the lock file in dbmodify.c.
    – jordanm
    Apr 8, 2013 at 16:18
  • @patrick lockfile is "lock", not the database.
    – jordanm
    Apr 8, 2013 at 16:27
  • then why does flock -x /var/lib/dpkg/lock dpkg -r somepackage work?
    – phemmer
    Apr 8, 2013 at 16:30
  • @Patrick a lock doesn't stick around after the caller process exits.
    – jordanm
    Apr 8, 2013 at 16:34
1

dpkg has always used fcntl(2) advisory record locks. This means the locks are associated with a process, and thus the lock files must never be removed, or they might cause database or filesystem damage due to possibly two or more dpkg instanced ending running concurrently.

It is always preferable to kill a running dpkg instance if that ends up being required (because dpkg is supposed to be resilient against sudden entire system crashes and abrupt termination, and problems arising from that would be considered serious bugs in need of fixing), than ever considering removing the lock files.

This is documented in the dpkg frontend spec, and in the dpkg FAQ.

0

As I see, dpkg locks the file /var/lib/dpkg/lock using lockf(3), which in turn uses fcntl(2).

$ sudo strace dpkg -r somepackage 2>&1 |
> grep F_SETLKW
fcntl64(5, F_SETLKW64, {l_type=F_WRLCK, l_whence=SEEK_SET, l_start=0, l_len=0}) = 0

This means that you cannot lock the file from the shell using flock(1), because this calls flock(2), which in many systems doesn't interact with fnctl locks.

$ sudo strace flock -x /var/lib/dpkg/lock 2>&1 |
> grep 'flock('
flock(3, LOCK_EX)

You can however lock the file with the with-lock-ex program or this Python script, both of which acquire a compatible lock.

1
  • AFAIK dpkg has never used lockf(3), at least from its VCS history, the first commit recorded there was already using fcntl(2). While this distinction is indeed immaterial on at least GNU/Linux, assuming that lockf(3) will use fnctl(2) underneath or will use compatible locks is not a safe and portable assumption to make. Aug 8, 2021 at 21:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.