Locking
As HAL is a mechanism that enables programs in a desktop session
to enforce the policy of the users choice, unexpected things can
happen. For example, if the user is in the middle of partitioning
a disk drive, it is desirable to keep the desktop from mounting
partitions that have not yet been prepared with a suitable file
system. In fact, in such a situation data loss may be the result
if a volume have an old file system signature indicating it's
mountable and, simultenously, another tool is writing to the raw
block device. The mechanism that automounters use, HAL, provides
locking primitives to avoid this.
Further, for multi-user systems, several desktop sessions may run
on a system each on their own display. Suppose that one session
becomes idle and the power management daemon in that session
decides to suspend the system according to user preferences in the
idle session. The result is that users at other seats will see the
system suspend and this is not desirable. The power management
daemons in all sessions need to cooperate to ensure that the
system only suspends when e.g. all sessions are idle or not at
all. The mechanism that each power management daemon uses, HAL,
provides locking primitives that can be used to achieve this.
Overview
HAL provides a mechanism to lock a specific D-Bus interface
either for a specific device or for all the devices the caller
have access to.
The former is achieved by using
the AcquireInterfaceLock()
and ReleaseInterfaceLock() methods on
the org.freedesktop.Hal.Device interface that
every device object implements (see
). By using this API, a caller
can prevent any other caller from invoking methods on the given
interface for the given device object - other callers will
simply see
the org.freedesktop.Hal.Device.InterfaceLocked
exception if they attempt to invoke a method on the given
interface on the given device. The locker can specify whether
the lock is exclusive meaning if multiple
clients clients can hold the lock or if only one client can hold
the lock at one time. If a client don't have access to the
interface of the device, attempts to lock will fail with
a org.freedesktop.Hal.PermissionDenied
exception. If a client loses access to a device (say, if his
session is switched away from using fast user switching) while
holding a lock, he will lose the lock; this can be tracked by
listening to the InterfaceLockReleased
signal.
All local clients, whether they are active or not, can always
lock interfaces on the root computer device object (this doesn't
mean that they are privileged to use the interfaces though) -
the rationale is that this device object represents shared
infrastructure, e.g. power management, and even inactive
sessions needs to participate in managing this.
If another client already holds a lock exclusively, attempts
from other clients to acquire the lock will fail with
the org.freedesktop.Hal.Device.InterfaceAlreadyLocked
exception even if they have access to the device.
In addition, a client may opt to lock all devices that he got
access to by using
the AcquireGlobalInterfaceLock()
and ReleaseGlobalInterfaceLock() methods on
the org.freedesktop.Hal.Manager interface on
the /org/freedesktop/Hal/Manager object (see
). Global interface locks can
also be obtained exclusively if the caller so desires. Unlike
per-device interface locking, it is not checked at locking time
whether the locker have access to a given device; instead
checking is done when callers attempt to access the
interface.
The algorithm used for determining if a caller is locked out is
shown below. A caller A is locked out of an interface IFACE on a
device object DEVICE if, and only if,
Another caller B is holding a lock on the interface IFACE on
DEVICE and A don't have either a global lock on IFACE or a
lock on IFACE on DEVICE; or
Another caller B is holding the global lock on the
interface IFACE and B has access to DEVICE and and A don't
have either a global lock on IFACE or a lock on IFACE on
DEVICE.
In other words, a caller A can grab a global lock, but that
doesn't mean A can lock other clients out of devices that A
doesn't have access to. Specifically a caller is never locked
out if he has locked an interface either globally or on the
device in question. However, if two clients have a lock on a
device, then both can access it. To ensure that everyone is
locked out, a caller needs to use an exclusive lock.
Note that certain interfaces will also check whether other locks
are being held on other device objects. This is specified on a
per-interface basis in .
If a process holding locks disconnects from the system bus, the
locks being held by that process will be released.
Guidelines
Locking is only useful if applications requiring exclusive
access actually use the locking primitives to cooperate with
other applications. Here is a list of guidelines.
Disk Management / Partitioning
In order to prevent HAL-based automounters from mounting
partitions that are being prepared, applications that access
block devices directly (and pokes the kernel to reload the
partitioning table) should lock out automounters by either
a) obtaining
the org.freedesktop.Hal.Device.Storage
lock on each drive being processed; or b) obtaintaing the
global
org.freedesktop.Hal.Device.Storage
lock. This includes programs like fdisk, gparted, parted and
operating system installers. See also
and
the hal-lock(1) program and manual page.
Power Management
Typically, a desktop session includes a session-wide power
management daemon that enforces the policy of the users
choice, e.g. whether the system should suspend to ram on lid
close, whether to hibernate the system after the user being
idle for 30 minutes and so on. In a multi-user setup (both
fast user switching and multi-seat), this can break in
various interesting ways unless the power management daemons
cooperate. Also, there may be software running at the system
level who will want to inhibit a desktop session power
management daemon from suspending / shutting down.
System-level software that do not wish to be interrupted
by the effect of someone calling into the
org.freedesktop.Hal.Device.SystemPowerManagement
interface MUST hold the
org.freedesktop.Hal.Device.SystemPowerManagement
lock non-exclusively on the root computer device
object. For example, the YUM software updater should
hold the lock when doing an RPM transaction.
In addition, any power management session daemon instance
... MUST hold the org.freedesktop.Hal.Device.SystemPowerManagement lock
non-exclusively on the root computer device object
unless it is prepared to call into this interface
itself. This typically means that the PM daemon instance
simply acquires the lock on start up and releases it
just before it calls into
the org.freedesktop.Hal.Device.SystemPowerManagement
interface. In other words, the PM daemon instance needs
to hold the lock exactly when it doesn't want other PM
daemon instances to call into
the org.freedesktop.Hal.Device.SystemPowerManagement interface.
This means that if the user have configured the PM
daemon instance to go to sleep after 30 minutes of
inactivity, the lock should be released then.
... MUST not hold the lock when the session is inactive
(fast user switching) UNLESS an application in the
session have explicitly called Inhibit() on
the org.freedesktop.PowerManagement
D-Bus session bus interface of the PM daemon.
... MUST check that no other process is holding the lock (using the IsLockedByOthers method on the standard org.freedesktop.Hal.Device interface)
before calling into
the org.freedesktop.Hal.Device.SystemPowerManagement
interface. If another process is holding the lock, it
means that either 1) another session is not prepared to
call into
the org.freedesktop.Hal.Device.SystemPowerManagement
interface; OR 2) some system-level software is holding
the lock. The PM daemon instance MUST respect this by
not calling into
the org.freedesktop.Hal.Device.SystemPowerManagement
interface itself.
However, any Power management daemon instance
... MAY prompt the user, if applicable, to ask if she
still wants to perform the requested action (e.g. call
into
the org.freedesktop.Hal.Device.SystemPowerManagement
interface) despite the fact that another process
(possibly from another user) is indicating that it does
not want the system to e.g. suspend. Only if the user
agrees, the power management instance should call into
the org.freedesktop.Hal.Device.SystemPowerManagement
interface. Typically, it's only useful to prompt the
user with such questions if the request to call into
the org.freedesktop.Hal.Device.SystemPowerManagement
interface originates from user input, e.g. either a
hotkey, the user clicking a suspend button in the UI or
an application invoking the Suspend() method on the
org.freedesktop.PowerManagement D-Bus
session interface of the PM daemon.
... MAY ignore that other processes are holding the lock
and call into
the org.freedesktop.Hal.Device.SystemPowerManagement
interface anyway, but ONLY if if the request to call
into
the org.freedesktop.Hal.Device.SystemPowerManagement
interface originated from e.g. lid close, critically low
battery or other similar conditions.
... MAY still call SetPowerSave() on
the org.freedesktop.Hal.Device.SystemPowerManagement
interface even if other processes are holding the lock.