Frontend locking in APT clients

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Frontend locking in APT clients

Julian Andres Klode-4
Hi folks,

With frontend locking in dpkg git, I think it's time I clear up
some potential confusion as to how this is supposed to work in the
APT world.

The idea is that the current _system->Lock() / apt_pkg.SystemLock
/ apt_pkg.pkgsystem_lock() will start to manage _both_ lock-frontend
and lock, and new methods LockInner() and UnlockInner() will be
provided to release "lock". Code running dpkg will need to call
those around dpkg runs, rather than the generic Lock ones.

python-apt is currently broken in that you need to release the lock
prior to calling commit() on an apt.Cache. This will change soon
- no unlocking will be needed. A python-apt (>> 1.7~alpha1~) client
should behave as following:

Basically, add Depends: python-apt (>> 1.7~alpha1~), and do:
  with apt_pkg.SystemLock():
    main()
- forget about locks if you don't invoke dpkg manually - do not
release that, ever. If you do run dpkg manually do it like this:

  with apt_pkg.NoInnerLock():
    subprocess.check_call(["dpkg", "--configure", "-a"])

or instead of context managers, use the functions
pkgsystem_{un,}lock{,_inner}.

This will ensure that your apt client will be safe against
any other apt client, and any other client implementing frontend
locking. It will not be safe against other frontends that acquire
the dpkg lock themselves, those will need fixing too. It will however,
be safe against concurrent runs of dpkg by users or frontends not
implementing locking.

Thanks,
Julian
--
debian developer - deb.li/jak | jak-linux.org - free software dev
ubuntu core developer                              i speak de, en

Reply | Threaded
Open this post in threaded view
|

Re: Frontend locking in APT clients

Julian Andres Klode-4
On Mon, Jun 18, 2018 at 08:19:17PM +0200, Julian Andres Klode wrote:

> Hi folks,
>
> With frontend locking in dpkg git, I think it's time I clear up
> some potential confusion as to how this is supposed to work in the
> APT world.
>
> The idea is that the current _system->Lock() / apt_pkg.SystemLock
> / apt_pkg.pkgsystem_lock() will start to manage _both_ lock-frontend
> and lock, and new methods LockInner() and UnlockInner() will be
> provided to release "lock". Code running dpkg will need to call
> those around dpkg runs, rather than the generic Lock ones.
>
> python-apt is currently broken in that you need to release the lock
> prior to calling commit() on an apt.Cache. This will change soon
> - no unlocking will be needed. A python-apt (>> 1.7~alpha1~) client
> should behave as following:
>
> Basically, add Depends: python-apt (>> 1.7~alpha1~), and do:
>   with apt_pkg.SystemLock():
>     main()
> - forget about locks if you don't invoke dpkg manually - do not
> release that, ever. If you do run dpkg manually do it like this:
>
>   with apt_pkg.NoInnerLock():
>     subprocess.check_call(["dpkg", "--configure", "-a"])

I want to note that apt in its current merge request state,
automatically sets DPKG_FRONTEND_LOCKED when invoking dpkg
if the system lock is acquired (after the fork, directly
before the execvp). If you run dpkg yourself, like for calling
dpkg --configure -a you will probably have to set the environment
variable yourself.

So you'll need:

  with apt_pkg.NoInnerLock():
    os.putenv("DPKG_FRONTEND_LOCKED", "1")
    subprocess.check_call(["dpkg", "--configure", "-a"])


I thought about making Lock() set the variable and unlock unset
it, but I'm not sure about implicatiomns wrt other subprocesses
like hooks.

--
debian developer - deb.li/jak | jak-linux.org - free software dev
ubuntu core developer                              i speak de, en