mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-21 12:03:55 -08:00
New D-Bus functions to support systemd inhibitor locks
* doc/misc/dbus.texi (Top): Add "Inhibitor Locks" submenu. Remove trailing period from chapter and section titles. (Inhibitor Locks): New node. * etc/NEWS: New D-Bus functions to support systemd inhibitor locks. Presentational fixes and improvements. * src/dbusbind.c (xd_registered_inhibitor_locks): New variable. (Fdbus_make_inhibitor_lock, Fdbus_close_inhibitor_lock) (Fdbus_registered_inhibitor_locks): New DEFUNs. (Bug#79963) (syms_of_dbusbind_for_pdumper): Initialize `xd_registered_inhibitor_locks'. (syms_of_dbusbind): Declare subroutines `Sdbus_make_inhibitor_lock', `Sdbus_close_inhibitor_lock' and `Sdbus_registered_inhibitor_locks'. Declare symbol `Qdbus_call_method'. staticpro `xd_registered_inhibitor_locks'. * test/lisp/net/dbus-tests.el (dbus--test-systemd-service) (dbus--test-systemd-path, dbus--test-systemd-manager-interface): New defconsts. (dbus-test10-inhibitor-locks): New test.
This commit is contained in:
parent
6287637ccd
commit
ab77b4b60c
4 changed files with 348 additions and 29 deletions
|
|
@ -64,6 +64,7 @@ another. An overview of D-Bus can be found at
|
|||
* Alternative Buses:: Alternative buses and environments.
|
||||
* Errors and Events:: Errors and events.
|
||||
* Monitoring Messages:: Monitoring messages.
|
||||
* Inhibitor Locks:: Inhibit system shutdowns and sleep states.
|
||||
* Index:: Index including concepts, functions, variables.
|
||||
|
||||
* GNU Free Documentation License:: The license for this documentation.
|
||||
|
|
@ -124,7 +125,7 @@ name could be @samp{org.gnu.Emacs.TextEditor} or
|
|||
|
||||
|
||||
@node Inspection
|
||||
@chapter Inspection of D-Bus services.
|
||||
@chapter Inspection of D-Bus services
|
||||
@cindex inspection
|
||||
|
||||
@menu
|
||||
|
|
@ -139,7 +140,7 @@ name could be @samp{org.gnu.Emacs.TextEditor} or
|
|||
|
||||
|
||||
@node Version
|
||||
@section D-Bus version.
|
||||
@section D-Bus version
|
||||
|
||||
D-Bus has evolved over the years. New features have been added with
|
||||
new D-Bus versions. There are two variables, which allow the determination
|
||||
|
|
@ -158,7 +159,7 @@ It is also @code{nil}, if it cannot be determined at runtime.
|
|||
|
||||
|
||||
@node Bus names
|
||||
@section Bus names.
|
||||
@section Bus names
|
||||
|
||||
There are several basic functions which inspect the buses for
|
||||
registered names. Internally they use the basic interface
|
||||
|
|
@ -267,7 +268,7 @@ at D-Bus @var{bus}, as a string.
|
|||
|
||||
|
||||
@node Introspection
|
||||
@section Knowing the details of D-Bus services.
|
||||
@section Knowing the details of D-Bus services
|
||||
|
||||
D-Bus services publish their interfaces. This can be retrieved and
|
||||
analyzed during runtime, in order to understand the used
|
||||
|
|
@ -483,7 +484,7 @@ If @var{object} has no @var{attribute}, the function returns
|
|||
|
||||
|
||||
@node Nodes and Interfaces
|
||||
@section Detecting object paths and interfaces.
|
||||
@section Detecting object paths and interfaces
|
||||
|
||||
The first elements, to be introspected for a D-Bus object, are further
|
||||
object paths and interfaces.
|
||||
|
|
@ -593,7 +594,7 @@ data from a running system:
|
|||
|
||||
|
||||
@node Methods and Signal
|
||||
@section Applying the functionality.
|
||||
@section Applying the functionality
|
||||
|
||||
Methods and signals are the communication means to D-Bus. The
|
||||
following functions return their specifications.
|
||||
|
|
@ -673,7 +674,7 @@ Example:
|
|||
|
||||
|
||||
@node Properties and Annotations
|
||||
@section What else to know about interfaces.
|
||||
@section What else to know about interfaces
|
||||
|
||||
Interfaces can have properties. These can be exposed via the
|
||||
@samp{org.freedesktop.DBus.Properties} interface@footnote{See
|
||||
|
|
@ -894,7 +895,7 @@ An attribute value can be retrieved by
|
|||
|
||||
|
||||
@node Arguments and Signatures
|
||||
@section The final details.
|
||||
@section The final details
|
||||
|
||||
Methods and signals have arguments. They are described in the
|
||||
@code{arg} XML elements.
|
||||
|
|
@ -962,7 +963,7 @@ non-@code{nil}, @var{direction} must be @samp{out}. Example:
|
|||
|
||||
|
||||
@node Type Conversion
|
||||
@chapter Mapping Lisp types and D-Bus types.
|
||||
@chapter Mapping Lisp types and D-Bus types
|
||||
@cindex type conversion
|
||||
|
||||
D-Bus method calls and signals accept usually several arguments as
|
||||
|
|
@ -975,7 +976,7 @@ applied Lisp object @expansion{} D-Bus type for input parameters, and
|
|||
D-Bus type @expansion{} Lisp object for output parameters.
|
||||
|
||||
|
||||
@section Input parameters.
|
||||
@section Input parameters
|
||||
|
||||
Input parameters for D-Bus methods and signals occur as arguments of a
|
||||
Lisp function call. The following mapping to D-Bus types is
|
||||
|
|
@ -1116,7 +1117,7 @@ lower-case hex digits. As a special case, "" is escaped to
|
|||
@end defun
|
||||
|
||||
|
||||
@section Output parameters.
|
||||
@section Output parameters
|
||||
|
||||
Output parameters of D-Bus methods and signals are mapped to Lisp
|
||||
objects.
|
||||
|
|
@ -1199,7 +1200,7 @@ that string:
|
|||
|
||||
|
||||
@node Synchronous Methods
|
||||
@chapter Calling methods in a blocking way.
|
||||
@chapter Calling methods in a blocking way
|
||||
@cindex method calls, synchronous
|
||||
@cindex synchronous method calls
|
||||
|
||||
|
|
@ -1319,7 +1320,7 @@ emulate the @code{lshal} command on GNU/Linux systems:
|
|||
|
||||
|
||||
@node Asynchronous Methods
|
||||
@chapter Calling methods non-blocking.
|
||||
@chapter Calling methods non-blocking
|
||||
@cindex method calls, asynchronous
|
||||
@cindex asynchronous method calls
|
||||
|
||||
|
|
@ -1371,7 +1372,7 @@ message arrives, and @var{handler} is called. Example:
|
|||
|
||||
|
||||
@node Register Objects
|
||||
@chapter Offering own services.
|
||||
@chapter Offering own services
|
||||
@cindex method calls, returning
|
||||
@cindex returning method calls
|
||||
|
||||
|
|
@ -1722,7 +1723,7 @@ to the service from D-Bus.
|
|||
|
||||
|
||||
@node Signals
|
||||
@chapter Sending and receiving signals.
|
||||
@chapter Sending and receiving signals
|
||||
@cindex signals
|
||||
|
||||
Signals are one way messages. They carry input parameters, which are
|
||||
|
|
@ -1859,7 +1860,7 @@ for a dummy signal, and check the result:
|
|||
|
||||
|
||||
@node Alternative Buses
|
||||
@chapter Alternative buses and environments.
|
||||
@chapter Alternative buses and environments
|
||||
@cindex bus names
|
||||
@cindex UNIX domain socket
|
||||
@cindex TCP/IP socket
|
||||
|
|
@ -1986,7 +1987,7 @@ running. This could be achieved by
|
|||
|
||||
|
||||
@node Errors and Events
|
||||
@chapter Errors and events.
|
||||
@chapter Errors and events
|
||||
@cindex debugging
|
||||
@cindex errors
|
||||
@cindex events
|
||||
|
|
@ -2145,7 +2146,7 @@ whether a given D-Bus error is related to them.
|
|||
|
||||
|
||||
@node Monitoring Messages
|
||||
@chapter Monitoring messages.
|
||||
@chapter Monitoring messages
|
||||
@cindex monitoring
|
||||
|
||||
@defun dbus-register-monitor bus &optional handler &key type sender destination path interface member
|
||||
|
|
@ -2204,6 +2205,111 @@ switches to the monitor buffer.
|
|||
@end deffn
|
||||
|
||||
|
||||
@node Inhibitor Locks
|
||||
@chapter Inhibit system shutdowns and sleep states
|
||||
|
||||
@uref{https://systemd.io/INHIBITOR_LOCKS/, Systemd} includes a logic to
|
||||
inhibit system shutdowns and sleep states. It can be controlled by a
|
||||
D-Bus API@footnote{@uref{https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html}}.
|
||||
Because this API includes handling of file descriptors, not all
|
||||
functions can be implemented by simple D-Bus method calls. Therefore,
|
||||
the following functions are provided.
|
||||
|
||||
@defun dbus-make-inhibitor-lock what why &optional block
|
||||
This function creates an inhibitor for system shutdowns and sleep states.
|
||||
|
||||
@var{what} is a colon-separated string of lock types: @samp{shutdown},
|
||||
@samp{sleep}, @samp{idle}, @samp{handle-power-key},
|
||||
@samp{handle-suspend-key}, @samp{handle-hibernate-key},
|
||||
@samp{handle-lid-switch}. Example: @samp{shutdown:idle}.
|
||||
|
||||
@c@var{who} is a descriptive string of who is taking the lock. If it is
|
||||
@c@code{nil}, it defaults to @samp{Emacs}.
|
||||
|
||||
@var{why} is a descriptive string of why the lock is taken. Example:
|
||||
@samp{Package Update in Progress}.
|
||||
|
||||
The optional @var{block} is the mode of the inhibitor lock, either
|
||||
@samp{block} (@var{block} is non-@code{nil}), or @samp{delay}.
|
||||
|
||||
Note, that the @code{who} argument of the inhibitor lock object of the
|
||||
systemd manager is always set to the string @samp{Emacs}.
|
||||
|
||||
It returns a file descriptor or @code{nil}, if the lock cannot be
|
||||
acquired. If there is already an inhibitor lock for the triple
|
||||
@code{(WHAT WHY BLOCK)}, this lock is returned. Example:
|
||||
|
||||
@lisp
|
||||
(dbus-make-inhibitor-lock "sleep" "Test")
|
||||
|
||||
@result{} 25
|
||||
@end lisp
|
||||
@end defun
|
||||
|
||||
@defun dbus-registered-inhibitor-locks
|
||||
Return registered inhibitor locks, an alist.
|
||||
This allows to check, whether other packages of the running Emacs
|
||||
instance have acquired an inhibitor lock as well.
|
||||
|
||||
An entry in this list is a list @code{(@var{fd} @var{what} @var{why}
|
||||
@var{block})}. The car of the list is the file descriptor retrieved
|
||||
from a @code{dbus-make-inhibitor-lock} call. The cdr of the list
|
||||
represents the three arguments @code{dbus-make-inhibitor-lock} was
|
||||
called with. Example:
|
||||
|
||||
@lisp
|
||||
(dbus-registered-inhibitor-locks)
|
||||
|
||||
@result{} ((25 "sleep" "Test" nil))
|
||||
@end lisp
|
||||
@end defun
|
||||
|
||||
@defun dbus-close-inhibitor-lock lock
|
||||
Close inhibitor lock file descriptor.
|
||||
|
||||
@var{lock}, a file descriptor, must be the result of a
|
||||
@code{dbus-make-inhibitor-lock} call. It returns @code{t} in case of
|
||||
success, or @code{nil} if it isn't be possible to close the lock, or if
|
||||
the lock is closed already. Example:
|
||||
|
||||
@lisp
|
||||
(dbus-close-inhibitor-lock 25)
|
||||
|
||||
@result{} t
|
||||
|
||||
@end lisp
|
||||
@end defun
|
||||
|
||||
A typical scenario for these functions is to register for the
|
||||
D-Bus signal @samp{org.freedesktop.login1.Manager.PrepareForSleep}:
|
||||
|
||||
@lisp
|
||||
(defvar my-inhibitor-lock
|
||||
(dbus-make-inhibitor-lock "sleep" "Test"))
|
||||
|
||||
(defun my-dbus-PrepareForSleep-handler (start)
|
||||
(if start ;; The system goes down for sleep
|
||||
(progn
|
||||
@dots{}
|
||||
;; Release inhibitor lock.
|
||||
(when (natnump my-inhibitor-lock)
|
||||
(dbus-close-inhibitor-lock my-inhibitor-lock)
|
||||
(setq my-inhibitor-lock nil)))
|
||||
;; Reacquire inhibitor lock.
|
||||
(setq my-inhibitor-lock
|
||||
(dbus-make-inhibitor-lock "sleep" "Test"))))
|
||||
|
||||
(dbus-register-signal
|
||||
:system "org.freedesktop.login1" "/org/freedesktop/login1/Manager"
|
||||
"org.freedesktop.login1.Manager" "PrepareForSleep"
|
||||
#'my-dbus-PrepareForSleep-handler)
|
||||
|
||||
@result{} ((:signal :system "org.freedesktop.login1.Manager" "PrepareForSleep")
|
||||
("org.freedesktop.login1" "/org/freedesktop/login1/Manager"
|
||||
my-dbus-PrepareForSleep-handler))
|
||||
@end lisp
|
||||
|
||||
|
||||
@node Index
|
||||
@unnumbered Index
|
||||
|
||||
|
|
|
|||
33
etc/NEWS
33
etc/NEWS
|
|
@ -201,10 +201,10 @@ large or inefficient completion tables this can slow down typing.
|
|||
|
||||
+++
|
||||
*** New optional value of 'minibuffer-visible-completions'.
|
||||
If the value of this option is 'up-down', only the <UP> and <DOWN> arrow
|
||||
keys move point between candidates shown in the *Completions* buffer
|
||||
display, while <RIGHT> and <LEFT> arrows move point in the minibuffer
|
||||
window.
|
||||
If the value of this option is 'up-down', only the '<up>' and '<down>'
|
||||
arrow keys move point between candidates shown in the "*Completions*"
|
||||
buffer display, while '<right>' and '<left>' arrows move point in the
|
||||
minibuffer window.
|
||||
|
||||
---
|
||||
*** 'RET' chooses the completion selected with 'M-<up>/M-<down>'.
|
||||
|
|
@ -513,7 +513,7 @@ Each non-tooltip frame is assigned a unique integer id. This allows you
|
|||
to unambiguously identify frames even if they share the same name or
|
||||
title. When 'undelete-frame-mode' is enabled, each deleted frame's id
|
||||
is stored for resurrection. The function 'frame-id' returns a frame's
|
||||
id (in C, use the frame struct member id).
|
||||
id (in C, use the frame struct member 'id').
|
||||
|
||||
** Mode Line
|
||||
|
||||
|
|
@ -2062,9 +2062,9 @@ you exit the Emacs session or kill the IELM buffer.
|
|||
|
||||
---
|
||||
*** New value 'point' for user option 'ielm-dynamic-return'.
|
||||
When 'ielm-dynamic-return' is set to 'point', typing RET has dynamic
|
||||
When 'ielm-dynamic-return' is set to 'point', typing 'RET' has dynamic
|
||||
behavior based on whether point is inside an sexp. While point is
|
||||
inside an sexp typing RET inserts a newline, and otherwise Emacs
|
||||
inside an sexp typing 'RET' inserts a newline, and otherwise Emacs
|
||||
proceeds with evaluating the expression. This is useful when
|
||||
'electric-pair-mode', or a similar automatic pairing mode, is enabled.
|
||||
|
||||
|
|
@ -2889,7 +2889,7 @@ The user option 'package-review-policy' can configure which packages
|
|||
the user should be allowed to review before any processing takes place.
|
||||
The package review can include reading the downloaded source code,
|
||||
presenting a diff between the downloaded code and a previous
|
||||
installation or displaying a changelog.
|
||||
installation or displaying a ChangeLog.
|
||||
|
||||
** Rcirc
|
||||
|
||||
|
|
@ -3750,12 +3750,21 @@ without marking it as automatically buffer-local.
|
|||
** The obsolete face attribute ':reverse-video' has been removed.
|
||||
Use ':inverse-video' instead.
|
||||
|
||||
** D-Bus
|
||||
|
||||
+++
|
||||
** Support interactive D-Bus authorization.
|
||||
*** Support interactive D-Bus authorization.
|
||||
A new ':authorizable t' parameter has been added to 'dbus-call-method'
|
||||
and 'dbus-call-method-asynchronously' to allow the user to interactively
|
||||
authorize the invoked D-Bus method (for example via polkit).
|
||||
|
||||
+++
|
||||
*** New D-Bus functions to support systemd inhibitor locks.
|
||||
The functions 'dbus-make-inhibitor-lock', 'dbus-close-inhibitor-lock'
|
||||
and 'dbus-registered-inhibitor-locks' implement acquiring and releasing
|
||||
systemd inhibitor locks. See the Info node "(dbus) Inhibitor Locks" for
|
||||
details.
|
||||
|
||||
** The customization group 'wp' has been removed.
|
||||
It has been obsolete since Emacs 26.1. Use the group 'text' instead.
|
||||
|
||||
|
|
@ -3926,15 +3935,17 @@ When the theme is set on PGTK, Android, or MS-Windows systems,
|
|||
variable 'toolkit-theme' as either symbol 'dark' or 'light', but may be
|
||||
extended to encompass other toolkit-specific symbols in the future.
|
||||
|
||||
** Progress reporter
|
||||
|
||||
+++
|
||||
** Progress reporter callbacks.
|
||||
*** Progress reporter callbacks.
|
||||
'make-progress-reporter' now accepts optional arguments UPDATE-CALLBACK,
|
||||
called on progress steps, and DONE-CALLBACK, called when the progress
|
||||
reporter is done. See the 'make-progress-reporter' docstring for a full
|
||||
specification of these new optional arguments.
|
||||
|
||||
+++
|
||||
** Progress reporter context.
|
||||
*** Progress reporter context.
|
||||
'make-progress-reporter' now accepts the optional argument CONTEXT,
|
||||
which if it is the symbol 'async', inhibits updates in the echo area
|
||||
when it is busy. This is useful, for example, if you want to monitor progress
|
||||
|
|
|
|||
109
src/dbusbind.c
109
src/dbusbind.c
|
|
@ -1617,6 +1617,109 @@ usage: (dbus-message-internal &rest REST) */)
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Alist of registered inhibitor locks for D-Bus.
|
||||
An entry in this list is a list (FD WHAT WHY BLOCK).
|
||||
The car of the list is a file descriptor retrieved from a
|
||||
'dbus-make-inhibitor-lock` call. The cdr of the list represents the
|
||||
three arguments 'dbus-make-inhibitor-lock` was called with. */
|
||||
static Lisp_Object xd_registered_inhibitor_locks;
|
||||
|
||||
DEFUN ("dbus-make-inhibitor-lock", Fdbus_make_inhibitor_lock,
|
||||
Sdbus_make_inhibitor_lock,
|
||||
2, 3, 0,
|
||||
doc: /* Inhibit system shutdowns and sleep states.
|
||||
|
||||
WHAT is a colon-separated string of lock types, i.e. "shutdown",
|
||||
"sleep", "idle", "handle-power-key", "handle-suspend-key",
|
||||
"handle-hibernate-key", "handle-lid-switch". Example: "shutdown:idle".
|
||||
|
||||
WHY is a descriptive string of why the lock is taken. Example: "Package
|
||||
Update in Progress".
|
||||
|
||||
The optional BLOCK is the mode of the inhibitor lock, either "block"
|
||||
(BLOCK is non-nil), or "delay".
|
||||
|
||||
It returns a file descriptor or nil, if the lock cannot be acquired. If
|
||||
there is already an inhibitor lock for the triple (WHAT WHY BLOCK), this
|
||||
lock is returned.
|
||||
|
||||
For details of the arguments, see Info node `(dbus)Inhibitor Locks'. */)
|
||||
(Lisp_Object what, Lisp_Object why, Lisp_Object block)
|
||||
{
|
||||
CHECK_STRING (what);
|
||||
CHECK_STRING (why);
|
||||
if (!NILP (block))
|
||||
block = Qt;
|
||||
Lisp_Object who = build_string ("Emacs");
|
||||
Lisp_Object mode =
|
||||
(NILP (block)) ? build_string ("delay") : build_string ("block");
|
||||
|
||||
/* Check, whether it is registered already. */
|
||||
Lisp_Object triple = list3 (what, why, block);
|
||||
Lisp_Object registered = Frassoc (triple, xd_registered_inhibitor_locks);
|
||||
if (!NILP (registered))
|
||||
return CAR_SAFE (registered);
|
||||
|
||||
/* Register lock. */
|
||||
Lisp_Object lock =
|
||||
calln (Qdbus_call_method, QCsystem,
|
||||
build_string ("org.freedesktop.login1"),
|
||||
build_string ("/org/freedesktop/login1"),
|
||||
build_string ("org.freedesktop.login1.Manager"),
|
||||
build_string ("Inhibit"), what, who, why, mode);
|
||||
|
||||
xd_registered_inhibitor_locks =
|
||||
Fcons (Fcons (lock, triple), xd_registered_inhibitor_locks);
|
||||
return lock;
|
||||
}
|
||||
|
||||
DEFUN ("dbus-close-inhibitor-lock", Fdbus_close_inhibitor_lock,
|
||||
Sdbus_close_inhibitor_lock,
|
||||
1, 1, 0,
|
||||
doc: /* Close inhibitor lock file descriptor.
|
||||
|
||||
LOCK, a file descriptor, must be the result of a `dbus-make-inhibitor-lock'
|
||||
call. It returns t in case of success, or nil if it isn't be possible
|
||||
to close the lock, or if the lock is closed already.
|
||||
|
||||
For details, see Info node `(dbus)Inhibitor Locks'. */)
|
||||
(Lisp_Object lock)
|
||||
{
|
||||
CHECK_FIXNUM (lock);
|
||||
|
||||
/* Check, whether it is registered. */
|
||||
Lisp_Object registered = assoc_no_quit (lock, xd_registered_inhibitor_locks);
|
||||
if (NILP (registered))
|
||||
return Qnil;
|
||||
else
|
||||
{
|
||||
xd_registered_inhibitor_locks =
|
||||
Fdelete (registered, xd_registered_inhibitor_locks);
|
||||
return (emacs_close (XFIXNAT (lock)) == 0) ? Qt : Qnil;
|
||||
}
|
||||
}
|
||||
|
||||
DEFUN ("dbus-registered-inhibitor-locks", Fdbus_registered_inhibitor_locks,
|
||||
Sdbus_registered_inhibitor_locks,
|
||||
0, 0, 0,
|
||||
doc: /* Return registered inhibitor locks, an alist.
|
||||
This allows to check, whether other packages of the running Emacs
|
||||
instance have acquired an inhibitor lock as well.
|
||||
An entry in this list is a list (FD WHAT WHY BLOCK).
|
||||
The car of the list is the file descriptor retrieved from a
|
||||
'dbus-make-inhibitor-lock` call. The cdr of the list represents the
|
||||
three arguments 'dbus-make-inhibitor-lock` was called with. */)
|
||||
()
|
||||
{
|
||||
/* We return a copy of xd_registered_inhibitor_locks, in order to
|
||||
protect it against malicious manipulation. */
|
||||
Lisp_Object registered = xd_registered_inhibitor_locks;
|
||||
Lisp_Object result = Qnil;
|
||||
for (; !NILP (registered); registered = CDR_SAFE (registered))
|
||||
result = Fcons (Fcopy_sequence (CAR_SAFE (registered)), result);
|
||||
return Fnreverse (result);
|
||||
}
|
||||
|
||||
/* Construct a D-Bus event, and store it into the input event queue. */
|
||||
static void
|
||||
xd_store_event (Lisp_Object handler, Lisp_Object handler_args,
|
||||
|
|
@ -1869,6 +1972,7 @@ static void
|
|||
syms_of_dbusbind_for_pdumper (void)
|
||||
{
|
||||
xd_registered_buses = Qnil;
|
||||
xd_registered_inhibitor_locks = Qnil;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1876,6 +1980,9 @@ syms_of_dbusbind (void)
|
|||
{
|
||||
defsubr (&Sdbus__init_bus);
|
||||
defsubr (&Sdbus_get_unique_name);
|
||||
defsubr (&Sdbus_make_inhibitor_lock);
|
||||
defsubr (&Sdbus_close_inhibitor_lock);
|
||||
defsubr (&Sdbus_registered_inhibitor_locks);
|
||||
|
||||
DEFSYM (Qdbus_message_internal, "dbus-message-internal");
|
||||
defsubr (&Sdbus_message_internal);
|
||||
|
|
@ -1930,6 +2037,7 @@ syms_of_dbusbind (void)
|
|||
|
||||
/* Miscellaneous Lisp symbols. */
|
||||
DEFSYM (Qdbus_get_name_owner, "dbus-get-name-owner");
|
||||
DEFSYM (Qdbus_call_method, "dbus-call-method");
|
||||
|
||||
DEFVAR_LISP ("dbus-compiled-version",
|
||||
Vdbus_compiled_version,
|
||||
|
|
@ -2035,6 +2143,7 @@ be called when the D-Bus reply message arrives. */);
|
|||
/* Initialize internal objects. */
|
||||
pdumper_do_now_and_after_load (syms_of_dbusbind_for_pdumper);
|
||||
staticpro (&xd_registered_buses);
|
||||
staticpro (&xd_registered_inhibitor_locks);
|
||||
|
||||
Fprovide (intern_c_string ("dbusbind"), Qnil);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,15 @@
|
|||
(defconst dbus--test-interface "org.gnu.Emacs.TestDBus.Interface"
|
||||
"Test interface.")
|
||||
|
||||
(defconst dbus--test-systemd-service "org.freedesktop.login1"
|
||||
"Systemd service.")
|
||||
|
||||
(defconst dbus--test-systemd-path "/org/freedesktop/login1"
|
||||
"Systemd object path.")
|
||||
|
||||
(defconst dbus--test-systemd-manager-interface "org.freedesktop.login1.Manager"
|
||||
"Systemd Manager interface.")
|
||||
|
||||
(defun dbus--test-availability (bus)
|
||||
"Test availability of D-Bus BUS."
|
||||
(should (dbus-list-names bus))
|
||||
|
|
@ -2295,6 +2304,90 @@ The argument EXPECTED-ARGS is a list of expected arguments for the method."
|
|||
;; Cleanup.
|
||||
(dbus-unregister-service :session dbus--test-service)))
|
||||
|
||||
(ert-deftest dbus-test10-inhibitor-locks ()
|
||||
"Check `dbus-*-inhibitor-locks'."
|
||||
:tags '(:expensive-test)
|
||||
(skip-unless dbus--test-enabled-system-bus)
|
||||
(skip-unless (dbus-ping :system dbus--test-systemd-service 1000))
|
||||
|
||||
(let (lock1 lock2)
|
||||
;; Create inhibitor lock.
|
||||
(setq lock1 (dbus-make-inhibitor-lock "sleep" "Test delay"))
|
||||
(should (natnump lock1))
|
||||
;; The lock is reported by systemd.
|
||||
(should
|
||||
(member
|
||||
(list "sleep" "Emacs" "Test delay" "delay" (user-uid) (emacs-pid))
|
||||
(dbus-call-method
|
||||
:system dbus--test-systemd-service dbus--test-systemd-path
|
||||
dbus--test-systemd-manager-interface "ListInhibitors")))
|
||||
;; The lock is registered internally.
|
||||
(should
|
||||
(member
|
||||
(list lock1 "sleep" "Test delay" nil)
|
||||
(dbus-registered-inhibitor-locks)))
|
||||
;; There exist a file descriptor.
|
||||
(when (file-directory-p (format "/proc/%d/fd" (emacs-pid)))
|
||||
(should (file-symlink-p (format "/proc/%d/fd/%d" (emacs-pid) lock1))))
|
||||
|
||||
;; It is not possible to modify registered inhibitor locks on Lisp level.
|
||||
(setcar (assoc lock1 (dbus-registered-inhibitor-locks)) 'malicious)
|
||||
(should (assoc lock1 (dbus-registered-inhibitor-locks)))
|
||||
(should-not (assoc 'malicious (dbus-registered-inhibitor-locks)))
|
||||
|
||||
;; Creating it again returns the same inhibitor lock.
|
||||
(should (= lock1 (dbus-make-inhibitor-lock "sleep" "Test delay")))
|
||||
|
||||
;; Create another inhibitor lock.
|
||||
(setq lock2 (dbus-make-inhibitor-lock "sleep" "Test block" 'block))
|
||||
(should (natnump lock2))
|
||||
(should-not (= lock1 lock2))
|
||||
;; The lock is reported by systemd.
|
||||
(should
|
||||
(member
|
||||
(list "sleep" "Emacs" "Test block" "block" (user-uid) (emacs-pid))
|
||||
(dbus-call-method
|
||||
:system dbus--test-systemd-service dbus--test-systemd-path
|
||||
dbus--test-systemd-manager-interface "ListInhibitors")))
|
||||
;; The lock is registered internally.
|
||||
(should
|
||||
(member
|
||||
(list lock2 "sleep" "Test block" t)
|
||||
(dbus-registered-inhibitor-locks)))
|
||||
;; There exist a file descriptor.
|
||||
(when (file-directory-p (format "/proc/%d/fd" (emacs-pid)))
|
||||
(should (file-symlink-p (format "/proc/%d/fd/%d" (emacs-pid) lock2))))
|
||||
|
||||
;; Close the first inhibitor lock.
|
||||
(should (dbus-close-inhibitor-lock lock1))
|
||||
;; The internal registration has gone.
|
||||
(should-not
|
||||
(member
|
||||
(list lock1 "sleep" "Test delay" nil)
|
||||
(dbus-registered-inhibitor-locks)))
|
||||
;; The file descriptor has been deleted.
|
||||
(when (file-directory-p (format "/proc/%d/fd" (emacs-pid)))
|
||||
(should-not (file-symlink-p (format "/proc/%d/fd/%d" (emacs-pid) lock1))))
|
||||
|
||||
;; Closing it again is a noop.
|
||||
(should-not (dbus-close-inhibitor-lock lock1))
|
||||
|
||||
;; Creating it again returns (another?) inhibitor lock.
|
||||
(setq lock1 (dbus-make-inhibitor-lock "sleep" "Test delay"))
|
||||
(should (natnump lock1))
|
||||
;; The lock is registered internally.
|
||||
(should
|
||||
(member
|
||||
(list lock1 "sleep" "Test delay" nil)
|
||||
(dbus-registered-inhibitor-locks)))
|
||||
;; There exist a file descriptor.
|
||||
(when (file-directory-p (format "/proc/%d/fd" (emacs-pid)))
|
||||
(should (file-symlink-p (format "/proc/%d/fd/%d" (emacs-pid) lock1))))
|
||||
|
||||
;; Close the inhibitor locks.
|
||||
(should (dbus-close-inhibitor-lock lock1))
|
||||
(should (dbus-close-inhibitor-lock lock2))))
|
||||
|
||||
(defun dbus-test-all (&optional interactive)
|
||||
"Run all tests for \\[dbus]."
|
||||
(interactive "p")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue