diff options
| author | Michael Albinus | 2026-02-07 11:32:54 +0100 |
|---|---|---|
| committer | Michael Albinus | 2026-02-07 11:32:54 +0100 |
| commit | 89209a83b60c87d97f0c05dbf6cb29ff3cdf3d5a (patch) | |
| tree | 7eb4fe230b36d619b51eeecd6c0a9868fa268b5b | |
| parent | e1524740bef6cee52e138a086e43988a16ed703e (diff) | |
| download | emacs-89209a83b60c87d97f0c05dbf6cb29ff3cdf3d5a.tar.gz emacs-89209a83b60c87d97f0c05dbf6cb29ff3cdf3d5a.zip | |
Support D-Bus file descriptor manipulation
* doc/misc/dbus.texi (Synchronous Methods): Adapt `dbus-call-method'.
(Asynchronous Methods): Adapt `dbus-call-method-asynchronously'.
(File Descriptors): New chapter, replaces Inhibitor Locks.
* etc/NEWS: Replace "New D-Bus functions to support systemd
inhibitor locks" by "Support D-Bus file descriptor manipulation".
Presentational fixes and improvements.
* lisp/net/dbus.el (dbus-call-method)
(dbus-call-method-asynchronously): Adapt docstring.
(dbus-list-hash-table): Return (nreverse result).
(dbus-monitor-goto-serial): Declare `completion'.
* src/dbusbind.c (Fdbus_message_internal, xd_read_message_1):
Handle `:keep-fd'.
(xd_registered_inhibitor_locks, Fdbus_make_inhibitor_lock)
(Fdbus_close_inhibitor_lock, Fdbus_registered_inhibitor_locks): Delete.
(xd_registered_fds): New variable.
(Fdbus__fd_open, Fdbus__fd_close, Fdbus__registered_fds):
New DEFUNs. (Bug#79963)
(syms_of_dbusbind_for_pdumper): Initialize `xd_registered_fds'.
(syms_of_dbusbind): Remove subroutines
`Sdbus_make_inhibitor_lock', `Sdbus_close_inhibitor_lock' and
`Sdbus_registered_inhibitor_locks'. Remove symbol `Qdbus_call_method'.
Declare subroutines `Sdbus__fd_open', `Sdbus__fd_close' and
`Sdbus__registered_fds'. Declare symbol `QCkeep_fd'. staticpro
`xd_registered_fds'.
* test/lisp/net/dbus-tests.el (dbus-test10-inhibitor-locks): Delete.
(dbus-test10-keep-fd, dbus-test10-open-close-fd): New tests.
| -rw-r--r-- | doc/misc/dbus.texi | 151 | ||||
| -rw-r--r-- | etc/NEWS | 24 | ||||
| -rw-r--r-- | lisp/net/dbus.el | 12 | ||||
| -rw-r--r-- | src/dbusbind.c | 188 | ||||
| -rw-r--r-- | test/lisp/net/dbus-tests.el | 167 |
5 files changed, 317 insertions, 225 deletions
diff --git a/doc/misc/dbus.texi b/doc/misc/dbus.texi index 59685087ae8..5b302c883ad 100644 --- a/doc/misc/dbus.texi +++ b/doc/misc/dbus.texi | |||
| @@ -64,7 +64,7 @@ another. An overview of D-Bus can be found at | |||
| 64 | * Alternative Buses:: Alternative buses and environments. | 64 | * Alternative Buses:: Alternative buses and environments. |
| 65 | * Errors and Events:: Errors and events. | 65 | * Errors and Events:: Errors and events. |
| 66 | * Monitoring Messages:: Monitoring messages. | 66 | * Monitoring Messages:: Monitoring messages. |
| 67 | * Inhibitor Locks:: Inhibit system shutdowns and sleep states. | 67 | * File Descriptors:: Handle file descriptors. |
| 68 | * Index:: Index including concepts, functions, variables. | 68 | * Index:: Index including concepts, functions, variables. |
| 69 | 69 | ||
| 70 | * GNU Free Documentation License:: The license for this documentation. | 70 | * GNU Free Documentation License:: The license for this documentation. |
| @@ -1212,7 +1212,7 @@ which carries the input parameters to the object owning the method to | |||
| 1212 | be called, and a reply message returning the resulting output | 1212 | be called, and a reply message returning the resulting output |
| 1213 | parameters from the object. | 1213 | parameters from the object. |
| 1214 | 1214 | ||
| 1215 | @defun dbus-call-method bus service path interface method &optional :timeout timeout :authorizable auth &rest args | 1215 | @defun dbus-call-method bus service path interface method &optional :timeout timeout :authorizable auth :keep-fd &rest args |
| 1216 | @anchor{dbus-call-method} | 1216 | @anchor{dbus-call-method} |
| 1217 | This function calls @var{method} on the D-Bus @var{bus}. @var{bus} is | 1217 | This function calls @var{method} on the D-Bus @var{bus}. @var{bus} is |
| 1218 | either the keyword @code{:system} or the keyword @code{:session}. | 1218 | either the keyword @code{:system} or the keyword @code{:session}. |
| @@ -1245,6 +1245,11 @@ running): | |||
| 1245 | @result{} "/org/freedesktop/systemd1/job/17508" | 1245 | @result{} "/org/freedesktop/systemd1/job/17508" |
| 1246 | @end lisp | 1246 | @end lisp |
| 1247 | 1247 | ||
| 1248 | If the parameter @code{:keep-fd} is given, and the return message has a | ||
| 1249 | first argument with a D-Bus type @code{:unix-fd}, the returned file | ||
| 1250 | descriptor is kept internally, and can be used in a later call of | ||
| 1251 | @code{dbus--close-fd} (@pxref{File Descriptors}). | ||
| 1252 | |||
| 1248 | The remaining arguments @var{args} are passed to @var{method} as | 1253 | The remaining arguments @var{args} are passed to @var{method} as |
| 1249 | arguments. They are converted into D-Bus types as described in | 1254 | arguments. They are converted into D-Bus types as described in |
| 1250 | @ref{Type Conversion}. | 1255 | @ref{Type Conversion}. |
| @@ -1324,7 +1329,7 @@ emulate the @code{lshal} command on GNU/Linux systems: | |||
| 1324 | @cindex method calls, asynchronous | 1329 | @cindex method calls, asynchronous |
| 1325 | @cindex asynchronous method calls | 1330 | @cindex asynchronous method calls |
| 1326 | 1331 | ||
| 1327 | @defun dbus-call-method-asynchronously bus service path interface method handler &optional :timeout timeout :authorizable auth &rest args | 1332 | @defun dbus-call-method-asynchronously bus service path interface method handler &optional :timeout timeout :authorizable auth :keep-fd &rest args |
| 1328 | This function calls @var{method} on the D-Bus @var{bus} | 1333 | This function calls @var{method} on the D-Bus @var{bus} |
| 1329 | asynchronously. @var{bus} is either the keyword @code{:system} or the | 1334 | asynchronously. @var{bus} is either the keyword @code{:system} or the |
| 1330 | keyword @code{:session}. | 1335 | keyword @code{:session}. |
| @@ -1347,6 +1352,11 @@ If the parameter @code{:authorizable} is given and the following | |||
| 1347 | @var{auth} is non-@code{nil}, the invoked method may interactively | 1352 | @var{auth} is non-@code{nil}, the invoked method may interactively |
| 1348 | prompt the user for authorization. The default is @code{nil}. | 1353 | prompt the user for authorization. The default is @code{nil}. |
| 1349 | 1354 | ||
| 1355 | If the parameter @code{:keep-fd} is given, and the return message has a | ||
| 1356 | first argument with a D-Bus type @code{:unix-fd}, the returned file | ||
| 1357 | descriptor is kept internally, and can be used in a later call of | ||
| 1358 | @code{dbus--close-fd} (@pxref{File Descriptors}). | ||
| 1359 | |||
| 1350 | The remaining arguments @var{args} are passed to @var{method} as | 1360 | The remaining arguments @var{args} are passed to @var{method} as |
| 1351 | arguments. They are converted into D-Bus types as described in | 1361 | arguments. They are converted into D-Bus types as described in |
| 1352 | @ref{Type Conversion}. | 1362 | @ref{Type Conversion}. |
| @@ -2205,109 +2215,90 @@ switches to the monitor buffer. | |||
| 2205 | @end deffn | 2215 | @end deffn |
| 2206 | 2216 | ||
| 2207 | 2217 | ||
| 2208 | @node Inhibitor Locks | 2218 | @node File Descriptors |
| 2209 | @chapter Inhibit system shutdowns and sleep states | 2219 | @chapter Handle file descriptors |
| 2210 | |||
| 2211 | @uref{https://systemd.io/INHIBITOR_LOCKS/, Systemd} includes a logic to | ||
| 2212 | inhibit system shutdowns and sleep states. It can be controlled by a | ||
| 2213 | D-Bus API@footnote{@uref{https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html}}. | ||
| 2214 | Because this API includes handling of file descriptors, not all | ||
| 2215 | functions can be implemented by simple D-Bus method calls. Therefore, | ||
| 2216 | the following functions are provided. | ||
| 2217 | |||
| 2218 | @defun dbus-make-inhibitor-lock what why &optional block | ||
| 2219 | This function creates an inhibitor for system shutdowns and sleep states. | ||
| 2220 | |||
| 2221 | @var{what} is a colon-separated string of lock types: @samp{shutdown}, | ||
| 2222 | @samp{sleep}, @samp{idle}, @samp{handle-power-key}, | ||
| 2223 | @samp{handle-suspend-key}, @samp{handle-hibernate-key}, | ||
| 2224 | @samp{handle-lid-switch}. Example: @samp{shutdown:idle}. | ||
| 2225 | |||
| 2226 | @c@var{who} is a descriptive string of who is taking the lock. If it is | ||
| 2227 | @c@code{nil}, it defaults to @samp{Emacs}. | ||
| 2228 | 2220 | ||
| 2229 | @var{why} is a descriptive string of why the lock is taken. Example: | 2221 | Methods offered by the D-Bus API could return a file descriptor, which |
| 2230 | @samp{Package Update in Progress}. | 2222 | must be handled further. This is indicated by the @code{:keep-fd} |
| 2223 | parameter when calling the method (@pxref{dbus-call-method}). | ||
| 2231 | 2224 | ||
| 2232 | The optional @var{block} is the mode of the inhibitor lock, either | 2225 | For example, @uref{https://systemd.io/INHIBITOR_LOCKS/, Systemd} |
| 2233 | @samp{block} (@var{block} is non-@code{nil}), or @samp{delay}. | 2226 | includes a logic to inhibit system shutdowns and sleep states. It can |
| 2234 | 2227 | be controlled by a the method @samp{Inhibit} of interface | |
| 2235 | Note, that the @code{who} argument of the inhibitor lock object of the | 2228 | @samp{org.freedesktop.login1.Manager}@footnote{@uref{https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html}}. |
| 2236 | systemd manager is always set to the string @samp{Emacs}. | 2229 | This function returns a file descriptor, which must be used to unlock |
| 2237 | 2230 | the locked resource, some of which lock the system. In order to keep | |
| 2238 | It returns a file descriptor or @code{nil}, if the lock cannot be | 2231 | this file descriptor internally, the respective D-Bus method call looks |
| 2239 | acquired. If there is already an inhibitor lock for the triple | 2232 | like (@var{what}, @var{who}, @var{why} and @var{mode} are |
| 2240 | @code{(WHAT WHY BLOCK)}, this lock is returned. Example: | 2233 | method-specific string arguments) |
| 2241 | 2234 | ||
| 2242 | @lisp | 2235 | @lisp |
| 2243 | (dbus-make-inhibitor-lock "sleep" "Test") | 2236 | (dbus-call-method |
| 2237 | :system | ||
| 2238 | "org.freedesktop.login1" "/org/freedesktop/login1" | ||
| 2239 | "org.freedesktop.login1.Manager" "Inhibit" | ||
| 2240 | :keep-fd WHAT WHO WHY MODE) | ||
| 2244 | 2241 | ||
| 2245 | @result{} 25 | 2242 | @result{} 25 |
| 2246 | @end lisp | 2243 | @end lisp |
| 2247 | @end defun | ||
| 2248 | 2244 | ||
| 2249 | @defun dbus-registered-inhibitor-locks | 2245 | The inhibition lock is unlocked, when the returned file descriptor is |
| 2250 | Return registered inhibitor locks, an alist. | 2246 | removed from the file system. This cannot be achieved on Lisp level. |
| 2251 | This allows to check, whether other packages of the running Emacs | 2247 | Therefore, there is the function @code{dbus--fd-close} to performs this |
| 2252 | instance have acquired an inhibitor lock as well. | 2248 | task (see below). |
| 2249 | |||
| 2250 | @strong{Note}: When the Emacs process itself dies, all such locks are | ||
| 2251 | released. | ||
| 2253 | 2252 | ||
| 2254 | An entry in this list is a list @code{(@var{fd} @var{what} @var{why} | 2253 | @strong{Note}: The following functions are internal to the D-Bus |
| 2255 | @var{block})}. The car of the list is the file descriptor retrieved | 2254 | implementation of Emacs. Use them with care. |
| 2256 | from a @code{dbus-make-inhibitor-lock} call. The cdr of the list | 2255 | |
| 2257 | represents the three arguments @code{dbus-make-inhibitor-lock} was | 2256 | @defun dbus--fd-open filename |
| 2258 | called with. Example: | 2257 | Open @var{filename} and return the respective read-only file descriptor. |
| 2258 | This is another function to keep a file descriptor internally. The | ||
| 2259 | returned file descriptor can be closed by @code{dbus--fd-close}. | ||
| 2260 | Example: | ||
| 2259 | 2261 | ||
| 2260 | @lisp | 2262 | @lisp |
| 2261 | (dbus-registered-inhibitor-locks) | 2263 | (dbus--fd-open "~/.emacs") |
| 2262 | 2264 | ||
| 2263 | @result{} ((25 "sleep" "Test" nil)) | 2265 | @result{} 20 |
| 2264 | @end lisp | 2266 | @end lisp |
| 2265 | @end defun | 2267 | @end defun |
| 2266 | 2268 | ||
| 2267 | @defun dbus-close-inhibitor-lock lock | 2269 | @defun dbus--fd-close fd |
| 2268 | Close inhibitor lock file descriptor. | 2270 | Close file descriptor @var{fd}. |
| 2269 | 2271 | @var{fd} must be the result of a @code{dbus-call-method} or | |
| 2270 | @var{lock}, a file descriptor, must be the result of a | 2272 | @code{dbus--fd-open} call, see @code{dbus--registered-fds}. It returns |
| 2271 | @code{dbus-make-inhibitor-lock} call. It returns @code{t} in case of | 2273 | @code{t} in case of success, or @code{nil} if it isn’t be possible to |
| 2272 | success, or @code{nil} if it isn't be possible to close the lock, or if | 2274 | close the file descriptor, or if the file descriptor is closed already. |
| 2273 | the lock is closed already. Example: | 2275 | Example: |
| 2274 | 2276 | ||
| 2275 | @lisp | 2277 | @lisp |
| 2276 | (dbus-close-inhibitor-lock 25) | 2278 | (dbus--fd-close 25) |
| 2277 | 2279 | ||
| 2278 | @result{} t | 2280 | @result{} t |
| 2279 | |||
| 2280 | @end lisp | 2281 | @end lisp |
| 2281 | @end defun | 2282 | @end defun |
| 2282 | 2283 | ||
| 2283 | A typical scenario for these functions is to register for the | 2284 | @defun dbus--registered-fds |
| 2284 | D-Bus signal @samp{org.freedesktop.login1.Manager.PrepareForSleep}: | 2285 | Return registered file descriptors, an alist. |
| 2286 | The key is an open file descriptor, retrieved via | ||
| 2287 | @code{dbus-call-method} or @code{dbus--open-fd}. The value is a string | ||
| 2288 | @var{object-path} or @var{filename}, which represents the arguments the | ||
| 2289 | function was called with. Those values are not needed for further | ||
| 2290 | operations; they are just shown for information. | ||
| 2285 | 2291 | ||
| 2286 | @lisp | 2292 | This alist allows to check, whether other packages of the running Emacs |
| 2287 | (defvar my-inhibitor-lock | 2293 | instance have acquired a file descriptor as well. Example: |
| 2288 | (dbus-make-inhibitor-lock "sleep" "Test")) | ||
| 2289 | 2294 | ||
| 2290 | (defun my-dbus-PrepareForSleep-handler (start) | 2295 | @lisp |
| 2291 | (if start ;; The system goes down for sleep | 2296 | (dbus--registered-fds) |
| 2292 | (progn | ||
| 2293 | @dots{} | ||
| 2294 | ;; Release inhibitor lock. | ||
| 2295 | (when (natnump my-inhibitor-lock) | ||
| 2296 | (dbus-close-inhibitor-lock my-inhibitor-lock) | ||
| 2297 | (setq my-inhibitor-lock nil))) | ||
| 2298 | ;; Reacquire inhibitor lock. | ||
| 2299 | (setq my-inhibitor-lock | ||
| 2300 | (dbus-make-inhibitor-lock "sleep" "Test")))) | ||
| 2301 | |||
| 2302 | (dbus-register-signal | ||
| 2303 | :system "org.freedesktop.login1" "/org/freedesktop/login1" | ||
| 2304 | "org.freedesktop.login1.Manager" "PrepareForSleep" | ||
| 2305 | #'my-dbus-PrepareForSleep-handler) | ||
| 2306 | 2297 | ||
| 2307 | @result{} ((:signal :system "org.freedesktop.login1.Manager" "PrepareForSleep") | 2298 | @result{} ((20 . "/home/user/.emacs") |
| 2308 | ("org.freedesktop.login1" "/org/freedesktop/login1" | 2299 | (25 . "/org/freedesktop/login1")) |
| 2309 | my-dbus-PrepareForSleep-handler)) | ||
| 2310 | @end lisp | 2300 | @end lisp |
| 2301 | @end defun | ||
| 2311 | 2302 | ||
| 2312 | 2303 | ||
| 2313 | @node Index | 2304 | @node Index |
| @@ -84,9 +84,9 @@ other directory on your system. You can also invoke the | |||
| 84 | 84 | ||
| 85 | +++ | 85 | +++ |
| 86 | ** 'line-spacing' now supports specifying spacing above the line. | 86 | ** 'line-spacing' now supports specifying spacing above the line. |
| 87 | Previously, only spacing below the line could be specified. The variable | 87 | Previously, only spacing below the line could be specified. The user |
| 88 | can now be set to a cons cell to specify spacing both above and below | 88 | option can now be set to a cons cell to specify spacing both above and |
| 89 | the line, which allows for vertically centering text. | 89 | below the line, which allows for vertically centering text. |
| 90 | 90 | ||
| 91 | +++ | 91 | +++ |
| 92 | ** 'prettify-symbols-mode' attempts to ignore undisplayable characters. | 92 | ** 'prettify-symbols-mode' attempts to ignore undisplayable characters. |
| @@ -1410,7 +1410,7 @@ is non-nil, this suffix is fontified using 'font-lock-type-face'. | |||
| 1410 | 1410 | ||
| 1411 | --- | 1411 | --- |
| 1412 | *** New user option 'yaml-ts-mode-yamllint-options'. | 1412 | *** New user option 'yaml-ts-mode-yamllint-options'. |
| 1413 | Additional options for 'yamllint' the command used for Flymake's YAML | 1413 | Additional options for 'yamllint', the command used for Flymake's YAML |
| 1414 | support. | 1414 | support. |
| 1415 | 1415 | ||
| 1416 | ** EIEIO | 1416 | ** EIEIO |
| @@ -2629,7 +2629,7 @@ When the argument is non-nil, the function switches to a buffer visiting | |||
| 2629 | the directory into which the repository was cloned. | 2629 | the directory into which the repository was cloned. |
| 2630 | 2630 | ||
| 2631 | +++ | 2631 | +++ |
| 2632 | *** 'vc-revert' is now bound to '@' in VC-Dir. | 2632 | *** 'vc-revert' is now bound to '@' in VC Directory. |
| 2633 | 2633 | ||
| 2634 | +++ | 2634 | +++ |
| 2635 | *** 'vc-revert' is now additionally bound to 'C-x v @'. | 2635 | *** 'vc-revert' is now additionally bound to 'C-x v @'. |
| @@ -2771,7 +2771,7 @@ base with the remote branch, including uncommitted changes. | |||
| 2771 | ('vc-root-log-outgoing-base') show the corresponding revision logs. | 2771 | ('vc-root-log-outgoing-base') show the corresponding revision logs. |
| 2772 | These are useful to view all outstanding (unmerged, unpushed) changes on | 2772 | These are useful to view all outstanding (unmerged, unpushed) changes on |
| 2773 | the current branch. They are also available as 'T =', 'T D', 'T l' and | 2773 | the current branch. They are also available as 'T =', 'T D', 'T l' and |
| 2774 | 'T L' in VC-Dir buffers. | 2774 | 'T L' in VC Directory buffers. |
| 2775 | 2775 | ||
| 2776 | +++ | 2776 | +++ |
| 2777 | *** New user option 'vc-use-incoming-outgoing-prefixes'. | 2777 | *** New user option 'vc-use-incoming-outgoing-prefixes'. |
| @@ -3858,11 +3858,13 @@ and 'dbus-call-method-asynchronously' to allow the user to interactively | |||
| 3858 | authorize the invoked D-Bus method (for example via polkit). | 3858 | authorize the invoked D-Bus method (for example via polkit). |
| 3859 | 3859 | ||
| 3860 | +++ | 3860 | +++ |
| 3861 | *** New D-Bus functions to support systemd inhibitor locks. | 3861 | *** Support D-Bus file descriptor manipulation. |
| 3862 | The functions 'dbus-make-inhibitor-lock', 'dbus-close-inhibitor-lock' | 3862 | A new ':keep-fd' parameter has been added to 'dbus-call-method' and |
| 3863 | and 'dbus-registered-inhibitor-locks' implement acquiring and releasing | 3863 | 'dbus-call-method-asynchronously' to instruct D-Bus to keep a file |
| 3864 | systemd inhibitor locks. See the Info node "(dbus) Inhibitor Locks" for | 3864 | descriptor, which has been returned by a method call, internally. The |
| 3865 | details. | 3865 | functions 'dbus--fd-open', 'dbus--fd-close' and 'dbus--registered-fds' |
| 3866 | implement managing these file descriptors. See the Info node "(dbus) | ||
| 3867 | File Descriptors" for details. | ||
| 3866 | 3868 | ||
| 3867 | ** The customization group 'wp' has been removed. | 3869 | ** The customization group 'wp' has been removed. |
| 3868 | It has been obsolete since Emacs 26.1. Use the group 'text' instead. | 3870 | It has been obsolete since Emacs 26.1. Use the group 'text' instead. |
diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el index 1c8f329fdd7..465de028725 100644 --- a/lisp/net/dbus.el +++ b/lisp/net/dbus.el | |||
| @@ -319,6 +319,10 @@ If the parameter `:authorizable' is given and the following AUTH | |||
| 319 | is non-nil, the invoked method may interactively prompt the user | 319 | is non-nil, the invoked method may interactively prompt the user |
| 320 | for authorization. The default is nil. | 320 | for authorization. The default is nil. |
| 321 | 321 | ||
| 322 | If the parameter `:keep-fd' is given, and the return message has a first | ||
| 323 | argument with a D-Bus type `:unix-fd', the returned file desriptor is | ||
| 324 | kept internally, and can be used in a later `dbus--close-fd' call. | ||
| 325 | |||
| 322 | All other arguments ARGS are passed to METHOD as arguments. They are | 326 | All other arguments ARGS are passed to METHOD as arguments. They are |
| 323 | converted into D-Bus types via the following rules: | 327 | converted into D-Bus types via the following rules: |
| 324 | 328 | ||
| @@ -453,6 +457,10 @@ If the parameter `:authorizable' is given and the following AUTH | |||
| 453 | is non-nil, the invoked method may interactively prompt the user | 457 | is non-nil, the invoked method may interactively prompt the user |
| 454 | for authorization. The default is nil. | 458 | for authorization. The default is nil. |
| 455 | 459 | ||
| 460 | If the parameter `:keep-fd' is given, and the return message has a first | ||
| 461 | argument with a D-Bus type `:unix-fd', the returned file desriptor is | ||
| 462 | kept internally, and can be used in a later `dbus--close-fd' call. | ||
| 463 | |||
| 456 | All other arguments ARGS are passed to METHOD as arguments. They are | 464 | All other arguments ARGS are passed to METHOD as arguments. They are |
| 457 | converted into D-Bus types via the following rules: | 465 | converted into D-Bus types via the following rules: |
| 458 | 466 | ||
| @@ -604,6 +612,7 @@ This is an internal function, it shall not be used outside dbus.el." | |||
| 604 | 612 | ||
| 605 | ;;; Hash table of registered functions. | 613 | ;;; Hash table of registered functions. |
| 606 | 614 | ||
| 615 | ;; Seems to be unused. Dow we want to keep it? | ||
| 607 | (defun dbus-list-hash-table () | 616 | (defun dbus-list-hash-table () |
| 608 | "Return all registered member registrations to D-Bus. | 617 | "Return all registered member registrations to D-Bus. |
| 609 | The return value is a list, with elements of kind (KEY . VALUE). | 618 | The return value is a list, with elements of kind (KEY . VALUE). |
| @@ -613,7 +622,7 @@ hash table." | |||
| 613 | (maphash | 622 | (maphash |
| 614 | (lambda (key value) (push (cons key value) result)) | 623 | (lambda (key value) (push (cons key value) result)) |
| 615 | dbus-registered-objects-table) | 624 | dbus-registered-objects-table) |
| 616 | result)) | 625 | (nreverse result))) |
| 617 | 626 | ||
| 618 | (defun dbus-setenv (bus variable value) | 627 | (defun dbus-setenv (bus variable value) |
| 619 | "Set the value of the BUS environment variable named VARIABLE to VALUE. | 628 | "Set the value of the BUS environment variable named VARIABLE to VALUE. |
| @@ -2098,6 +2107,7 @@ either a method name, a signal name, or an error name." | |||
| 2098 | 2107 | ||
| 2099 | (defun dbus-monitor-goto-serial () | 2108 | (defun dbus-monitor-goto-serial () |
| 2100 | "Goto D-Bus message with the same serial number." | 2109 | "Goto D-Bus message with the same serial number." |
| 2110 | (declare (completion ignore)) | ||
| 2101 | (interactive) | 2111 | (interactive) |
| 2102 | (when (mouse-event-p last-input-event) (mouse-set-point last-input-event)) | 2112 | (when (mouse-event-p last-input-event) (mouse-set-point last-input-event)) |
| 2103 | (when-let* ((point (get-text-property (point) 'dbus-serial))) | 2113 | (when-let* ((point (get-text-property (point) 'dbus-serial))) |
diff --git a/src/dbusbind.c b/src/dbusbind.c index 3cf3ec9897e..98adebfb2d4 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c | |||
| @@ -128,6 +128,8 @@ static bool xd_in_read_queued_messages = 0; | |||
| 128 | #endif | 128 | #endif |
| 129 | 129 | ||
| 130 | /* Check whether TYPE is a basic DBusType. */ | 130 | /* Check whether TYPE is a basic DBusType. */ |
| 131 | /* TODO: Shouldn't we assume, that recent D-Bus implementations carry | ||
| 132 | HAVE_DBUS_TYPE_IS_VALID and DBUS_TYPE_UNIX_FD? See configure.ac. */ | ||
| 131 | #ifdef HAVE_DBUS_TYPE_IS_VALID | 133 | #ifdef HAVE_DBUS_TYPE_IS_VALID |
| 132 | #define XD_BASIC_DBUS_TYPE(type) \ | 134 | #define XD_BASIC_DBUS_TYPE(type) \ |
| 133 | (dbus_type_is_valid (type) && dbus_type_is_basic (type)) | 135 | (dbus_type_is_valid (type) && dbus_type_is_basic (type)) |
| @@ -309,6 +311,8 @@ XD_OBJECT_TO_STRING (Lisp_Object object) | |||
| 309 | } \ | 311 | } \ |
| 310 | } while (0) | 312 | } while (0) |
| 311 | 313 | ||
| 314 | /* TODO: Shouldn't we assume, that recent D-Bus implementations carry | ||
| 315 | HAVE_DBUS_VALIDATE_*? See configure.ac. */ | ||
| 312 | #if (HAVE_DBUS_VALIDATE_BUS_NAME || HAVE_DBUS_VALIDATE_PATH \ | 316 | #if (HAVE_DBUS_VALIDATE_BUS_NAME || HAVE_DBUS_VALIDATE_PATH \ |
| 313 | || HAVE_DBUS_VALIDATE_INTERFACE || HAVE_DBUS_VALIDATE_MEMBER) | 317 | || HAVE_DBUS_VALIDATE_INTERFACE || HAVE_DBUS_VALIDATE_MEMBER) |
| 314 | #define XD_DBUS_VALIDATE_OBJECT(object, func) \ | 318 | #define XD_DBUS_VALIDATE_OBJECT(object, func) \ |
| @@ -1034,6 +1038,8 @@ xd_get_connection_address (Lisp_Object bus) | |||
| 1034 | } | 1038 | } |
| 1035 | 1039 | ||
| 1036 | /* Return the file descriptor for WATCH, -1 if not found. */ | 1040 | /* Return the file descriptor for WATCH, -1 if not found. */ |
| 1041 | /* TODO: Shouldn't we assume, that recent D-Bus implementations carry | ||
| 1042 | HAVE_DBUS_WATCH_GET_UNIX_FD? See configure.ac. */ | ||
| 1037 | static int | 1043 | static int |
| 1038 | xd_find_watch_fd (DBusWatch *watch) | 1044 | xd_find_watch_fd (DBusWatch *watch) |
| 1039 | { | 1045 | { |
| @@ -1349,6 +1355,7 @@ usage: (dbus-message-internal &rest REST) */) | |||
| 1349 | dbus_uint32_t serial = 0; | 1355 | dbus_uint32_t serial = 0; |
| 1350 | unsigned int ui_serial; | 1356 | unsigned int ui_serial; |
| 1351 | int timeout = -1; | 1357 | int timeout = -1; |
| 1358 | dbus_bool_t keepfd = FALSE; | ||
| 1352 | ptrdiff_t count, count0; | 1359 | ptrdiff_t count, count0; |
| 1353 | char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH]; | 1360 | char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH]; |
| 1354 | 1361 | ||
| @@ -1525,6 +1532,7 @@ usage: (dbus-message-internal &rest REST) */) | |||
| 1525 | timeout = min (XFIXNAT (args[count+1]), INT_MAX); | 1532 | timeout = min (XFIXNAT (args[count+1]), INT_MAX); |
| 1526 | count = count + 2; | 1533 | count = count + 2; |
| 1527 | } | 1534 | } |
| 1535 | |||
| 1528 | /* Check for authorizable parameter. */ | 1536 | /* Check for authorizable parameter. */ |
| 1529 | else if (EQ (args[count], QCauthorizable)) | 1537 | else if (EQ (args[count], QCauthorizable)) |
| 1530 | { | 1538 | { |
| @@ -1542,6 +1550,24 @@ usage: (dbus-message-internal &rest REST) */) | |||
| 1542 | 1550 | ||
| 1543 | count = count + 2; | 1551 | count = count + 2; |
| 1544 | } | 1552 | } |
| 1553 | |||
| 1554 | /* Check for keepfd parameter. */ | ||
| 1555 | else if (EQ (args[count], QCkeep_fd)) | ||
| 1556 | { | ||
| 1557 | if (mtype != DBUS_MESSAGE_TYPE_METHOD_CALL) | ||
| 1558 | XD_SIGNAL1 | ||
| 1559 | (build_string (":keep-fd is only supported on method calls")); | ||
| 1560 | |||
| 1561 | /* Ignore this keyword if unsupported. */ | ||
| 1562 | #ifdef DBUS_TYPE_UNIX_FD | ||
| 1563 | keepfd = TRUE; | ||
| 1564 | #else | ||
| 1565 | XD_DEBUG_MESSAGE (":keep-fd not supported"); | ||
| 1566 | #endif | ||
| 1567 | |||
| 1568 | ++count; | ||
| 1569 | } | ||
| 1570 | |||
| 1545 | else break; | 1571 | else break; |
| 1546 | 1572 | ||
| 1547 | } | 1573 | } |
| @@ -1595,7 +1621,8 @@ usage: (dbus-message-internal &rest REST) */) | |||
| 1595 | result = list3 (QCserial, bus, INT_TO_INTEGER (serial)); | 1621 | result = list3 (QCserial, bus, INT_TO_INTEGER (serial)); |
| 1596 | 1622 | ||
| 1597 | /* Create a hash table entry. */ | 1623 | /* Create a hash table entry. */ |
| 1598 | Fputhash (result, handler, Vdbus_registered_objects_table); | 1624 | Fputhash (result, keepfd ? Fcons (handler, path) : handler, |
| 1625 | Vdbus_registered_objects_table); | ||
| 1599 | } | 1626 | } |
| 1600 | else | 1627 | else |
| 1601 | { | 1628 | { |
| @@ -1617,106 +1644,81 @@ usage: (dbus-message-internal &rest REST) */) | |||
| 1617 | return result; | 1644 | return result; |
| 1618 | } | 1645 | } |
| 1619 | 1646 | ||
| 1620 | /* Alist of registered inhibitor locks for D-Bus. | 1647 | /* Alist of registered file descriptors for D-Bus. |
| 1621 | An entry in this list is a list (FD WHAT WHY BLOCK). | 1648 | The key is an open file descriptor, retrieved via `dbus-call-method' |
| 1622 | The car of the list is a file descriptor retrieved from a | 1649 | or `dbus--open-fd'. The value is a string OBJECT-PATH or FILENAME, |
| 1623 | 'dbus-make-inhibitor-lock` call. The cdr of the list represents the | 1650 | which represents the arguments the function was called with. Those |
| 1624 | three arguments 'dbus-make-inhibitor-lock` was called with. */ | 1651 | values are not needed for further operations; they are just shown for |
| 1625 | static Lisp_Object xd_registered_inhibitor_locks; | 1652 | information. */ |
| 1626 | 1653 | static Lisp_Object xd_registered_fds; | |
| 1627 | DEFUN ("dbus-make-inhibitor-lock", Fdbus_make_inhibitor_lock, | 1654 | |
| 1628 | Sdbus_make_inhibitor_lock, | 1655 | DEFUN ("dbus--fd-open", Fdbus__fd_open, Sdbus__fd_open, 1, 1, 0, |
| 1629 | 2, 3, 0, | 1656 | doc: /* Open FILENAME and return the respective read-only file descriptor. */) |
| 1630 | doc: /* Inhibit system shutdowns and sleep states. | 1657 | (Lisp_Object filename) |
| 1631 | |||
| 1632 | WHAT is a colon-separated string of lock types, i.e. "shutdown", | ||
| 1633 | "sleep", "idle", "handle-power-key", "handle-suspend-key", | ||
| 1634 | "handle-hibernate-key", "handle-lid-switch". Example: "shutdown:idle". | ||
| 1635 | |||
| 1636 | WHY is a descriptive string of why the lock is taken. Example: "Package | ||
| 1637 | Update in Progress". | ||
| 1638 | |||
| 1639 | The optional BLOCK is the mode of the inhibitor lock, either "block" | ||
| 1640 | (BLOCK is non-nil), or "delay". | ||
| 1641 | |||
| 1642 | It returns a file descriptor or nil, if the lock cannot be acquired. If | ||
| 1643 | there is already an inhibitor lock for the triple (WHAT WHY BLOCK), this | ||
| 1644 | lock is returned. | ||
| 1645 | |||
| 1646 | For details of the arguments, see Info node `(dbus)Inhibitor Locks'. */) | ||
| 1647 | (Lisp_Object what, Lisp_Object why, Lisp_Object block) | ||
| 1648 | { | 1658 | { |
| 1649 | CHECK_STRING (what); | 1659 | CHECK_STRING (filename); |
| 1650 | CHECK_STRING (why); | 1660 | filename = Fexpand_file_name (filename, Qnil); |
| 1651 | if (!NILP (block)) | 1661 | filename = ENCODE_FILE (filename); |
| 1652 | block = Qt; | ||
| 1653 | Lisp_Object who = build_string ("Emacs"); | ||
| 1654 | Lisp_Object mode = | ||
| 1655 | (NILP (block)) ? build_string ("delay") : build_string ("block"); | ||
| 1656 | 1662 | ||
| 1657 | /* Check, whether it is registered already. */ | 1663 | /* Check, whether it is registered already. */ |
| 1658 | Lisp_Object triple = list3 (what, why, block); | 1664 | Lisp_Object registered = Frassoc (filename, xd_registered_fds); |
| 1659 | Lisp_Object registered = Frassoc (triple, xd_registered_inhibitor_locks); | ||
| 1660 | if (!NILP (registered)) | 1665 | if (!NILP (registered)) |
| 1661 | return CAR_SAFE (registered); | 1666 | return CAR_SAFE (registered); |
| 1662 | 1667 | ||
| 1663 | /* Register lock. */ | 1668 | /* Open file descriptor. */ |
| 1664 | Lisp_Object lock = | 1669 | int fd = emacs_open (SSDATA (filename), O_RDONLY, 0); |
| 1665 | calln (Qdbus_call_method, QCsystem, | ||
| 1666 | build_string ("org.freedesktop.login1"), | ||
| 1667 | build_string ("/org/freedesktop/login1"), | ||
| 1668 | build_string ("org.freedesktop.login1.Manager"), | ||
| 1669 | build_string ("Inhibit"), what, who, why, mode); | ||
| 1670 | |||
| 1671 | xd_registered_inhibitor_locks = | ||
| 1672 | Fcons (Fcons (lock, triple), xd_registered_inhibitor_locks); | ||
| 1673 | return lock; | ||
| 1674 | } | ||
| 1675 | 1670 | ||
| 1676 | DEFUN ("dbus-close-inhibitor-lock", Fdbus_close_inhibitor_lock, | 1671 | if (fd <= 0) |
| 1677 | Sdbus_close_inhibitor_lock, | 1672 | XD_SIGNAL2 (build_string ("Cannot open file"), filename); |
| 1678 | 1, 1, 0, | ||
| 1679 | doc: /* Close inhibitor lock file descriptor. | ||
| 1680 | 1673 | ||
| 1681 | LOCK, a file descriptor, must be the result of a `dbus-make-inhibitor-lock' | 1674 | /* Register file descriptor. */ |
| 1682 | call. It returns t in case of success, or nil if it isn't be possible | 1675 | xd_registered_fds = |
| 1683 | to close the lock, or if the lock is closed already. | 1676 | Fcons (Fcons (INT_TO_INTEGER (fd), filename), xd_registered_fds); |
| 1677 | return INT_TO_INTEGER (fd); | ||
| 1678 | } | ||
| 1684 | 1679 | ||
| 1685 | For details, see Info node `(dbus)Inhibitor Locks'. */) | 1680 | DEFUN ("dbus--fd-close", Fdbus__fd_close, Sdbus__fd_close, 1, 1, 0, |
| 1686 | (Lisp_Object lock) | 1681 | doc: /* Close file descriptor FD. |
| 1682 | FD must be the result of a `dbus-call-method' or `dbus--fd-open' call, | ||
| 1683 | see `dbus--registered-fds'. It returns t in case of success, or nil if | ||
| 1684 | it isn't be possible to close the file descriptor, or if the file | ||
| 1685 | descriptor is closed already. */) | ||
| 1686 | (Lisp_Object fd) | ||
| 1687 | { | 1687 | { |
| 1688 | CHECK_FIXNUM (lock); | 1688 | CHECK_FIXNUM (fd); |
| 1689 | 1689 | ||
| 1690 | /* Check, whether it is registered. */ | 1690 | /* Check, whether it is registered. */ |
| 1691 | Lisp_Object registered = assoc_no_quit (lock, xd_registered_inhibitor_locks); | 1691 | Lisp_Object registered = assoc_no_quit (fd, xd_registered_fds); |
| 1692 | if (NILP (registered)) | 1692 | if (NILP (registered)) |
| 1693 | return Qnil; | 1693 | return Qnil; |
| 1694 | else | 1694 | else |
| 1695 | { | 1695 | { |
| 1696 | xd_registered_inhibitor_locks = | 1696 | xd_registered_fds = Fdelete (registered, xd_registered_fds); |
| 1697 | Fdelete (registered, xd_registered_inhibitor_locks); | 1697 | return (emacs_close (XFIXNAT (fd)) == 0) ? Qt : Qnil; |
| 1698 | return (emacs_close (XFIXNAT (lock)) == 0) ? Qt : Qnil; | ||
| 1699 | } | 1698 | } |
| 1700 | } | 1699 | } |
| 1701 | 1700 | ||
| 1702 | DEFUN ("dbus-registered-inhibitor-locks", Fdbus_registered_inhibitor_locks, | 1701 | DEFUN ("dbus--registered-fds", Fdbus__registered_fds, Sdbus__registered_fds, |
| 1703 | Sdbus_registered_inhibitor_locks, | ||
| 1704 | 0, 0, 0, | 1702 | 0, 0, 0, |
| 1705 | doc: /* Return registered inhibitor locks, an alist. | 1703 | doc: /* Return registered file descriptors, an alist. |
| 1706 | This allows to check, whether other packages of the running Emacs | 1704 | The key is an open file descriptor, retrieved via `dbus-call-method' or |
| 1707 | instance have acquired an inhibitor lock as well. | 1705 | `dbus--open-fd'. The value is a string OBJECT-PATH or FILENAME, which |
| 1708 | An entry in this list is a list (FD WHAT WHY BLOCK). | 1706 | represents the arguments the function was called with. Those values are |
| 1709 | The car of the list is the file descriptor retrieved from a | 1707 | not needed for further operations; they are just shown for information. |
| 1710 | 'dbus-make-inhibitor-lock` call. The cdr of the list represents the | 1708 | |
| 1711 | three arguments 'dbus-make-inhibitor-lock` was called with. */) | 1709 | This alist allows to check, whether other packages of the running Emacs |
| 1710 | instance have acquired a file descriptor as well. */) | ||
| 1712 | (void) | 1711 | (void) |
| 1713 | { | 1712 | { |
| 1714 | /* We return a copy of xd_registered_inhibitor_locks, in order to | 1713 | /* We return a copy of xd_registered_fds, in order to protect it |
| 1715 | protect it against malicious manipulation. */ | 1714 | against malicious manipulation. */ |
| 1716 | Lisp_Object registered = xd_registered_inhibitor_locks; | 1715 | Lisp_Object registered = xd_registered_fds; |
| 1717 | Lisp_Object result = Qnil; | 1716 | Lisp_Object result = Qnil; |
| 1718 | for (; !NILP (registered); registered = CDR_SAFE (registered)) | 1717 | for (; !NILP (registered); registered = CDR_SAFE (registered)) |
| 1719 | result = Fcons (Fcopy_sequence (CAR_SAFE (registered)), result); | 1718 | { |
| 1719 | Lisp_Object tem = CAR_SAFE (registered); | ||
| 1720 | result = Fcons (Fcons (CAR_SAFE (tem), CDR_SAFE (tem)), result); | ||
| 1721 | } | ||
| 1720 | return Fnreverse (result); | 1722 | return Fnreverse (result); |
| 1721 | } | 1723 | } |
| 1722 | 1724 | ||
| @@ -1836,7 +1838,22 @@ xd_read_message_1 (DBusConnection *connection, Lisp_Object bus) | |||
| 1836 | Fremhash (key, Vdbus_registered_objects_table); | 1838 | Fremhash (key, Vdbus_registered_objects_table); |
| 1837 | 1839 | ||
| 1838 | /* Store the event. */ | 1840 | /* Store the event. */ |
| 1839 | xd_store_event (value, args, event_args); | 1841 | xd_store_event (CONSP (value) ? CAR_SAFE (value) : value, args, event_args); |
| 1842 | |||
| 1843 | #ifdef DBUS_TYPE_UNIX_FD | ||
| 1844 | /* Check, whether there is a file descriptor to be kept. | ||
| 1845 | value is (handler . path) | ||
| 1846 | args is ((:unix-fd NN) ...) */ | ||
| 1847 | if (CONSP (value) | ||
| 1848 | && CONSP (CAR_SAFE (args)) | ||
| 1849 | && EQ (CAR_SAFE (CAR_SAFE (args)), QCunix_fd)) | ||
| 1850 | { | ||
| 1851 | xd_registered_fds = | ||
| 1852 | Fcons (Fcons (CAR_SAFE (CDR_SAFE (CAR_SAFE (args))), | ||
| 1853 | CDR_SAFE (value)), | ||
| 1854 | xd_registered_fds); | ||
| 1855 | } | ||
| 1856 | #endif | ||
| 1840 | } | 1857 | } |
| 1841 | 1858 | ||
| 1842 | else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */ | 1859 | else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */ |
| @@ -1972,7 +1989,7 @@ static void | |||
| 1972 | syms_of_dbusbind_for_pdumper (void) | 1989 | syms_of_dbusbind_for_pdumper (void) |
| 1973 | { | 1990 | { |
| 1974 | xd_registered_buses = Qnil; | 1991 | xd_registered_buses = Qnil; |
| 1975 | xd_registered_inhibitor_locks = Qnil; | 1992 | xd_registered_fds = Qnil; |
| 1976 | } | 1993 | } |
| 1977 | 1994 | ||
| 1978 | void | 1995 | void |
| @@ -1980,9 +1997,9 @@ syms_of_dbusbind (void) | |||
| 1980 | { | 1997 | { |
| 1981 | defsubr (&Sdbus__init_bus); | 1998 | defsubr (&Sdbus__init_bus); |
| 1982 | defsubr (&Sdbus_get_unique_name); | 1999 | defsubr (&Sdbus_get_unique_name); |
| 1983 | defsubr (&Sdbus_make_inhibitor_lock); | 2000 | defsubr (&Sdbus__fd_open); |
| 1984 | defsubr (&Sdbus_close_inhibitor_lock); | 2001 | defsubr (&Sdbus__fd_close); |
| 1985 | defsubr (&Sdbus_registered_inhibitor_locks); | 2002 | defsubr (&Sdbus__registered_fds); |
| 1986 | 2003 | ||
| 1987 | DEFSYM (Qdbus_message_internal, "dbus-message-internal"); | 2004 | DEFSYM (Qdbus_message_internal, "dbus-message-internal"); |
| 1988 | defsubr (&Sdbus_message_internal); | 2005 | defsubr (&Sdbus_message_internal); |
| @@ -2007,6 +2024,11 @@ syms_of_dbusbind (void) | |||
| 2007 | /* Lisp symbol for method interactive authorization. */ | 2024 | /* Lisp symbol for method interactive authorization. */ |
| 2008 | DEFSYM (QCauthorizable, ":authorizable"); | 2025 | DEFSYM (QCauthorizable, ":authorizable"); |
| 2009 | 2026 | ||
| 2027 | /* Lisp symbol for file descriptor kept. */ | ||
| 2028 | #ifdef DBUS_TYPE_UNIX_FD | ||
| 2029 | DEFSYM (QCkeep_fd, ":keep-fd"); | ||
| 2030 | #endif | ||
| 2031 | |||
| 2010 | /* Lisp symbols of D-Bus types. */ | 2032 | /* Lisp symbols of D-Bus types. */ |
| 2011 | DEFSYM (QCbyte, ":byte"); | 2033 | DEFSYM (QCbyte, ":byte"); |
| 2012 | DEFSYM (QCboolean, ":boolean"); | 2034 | DEFSYM (QCboolean, ":boolean"); |
| @@ -2143,7 +2165,7 @@ be called when the D-Bus reply message arrives. */); | |||
| 2143 | /* Initialize internal objects. */ | 2165 | /* Initialize internal objects. */ |
| 2144 | pdumper_do_now_and_after_load (syms_of_dbusbind_for_pdumper); | 2166 | pdumper_do_now_and_after_load (syms_of_dbusbind_for_pdumper); |
| 2145 | staticpro (&xd_registered_buses); | 2167 | staticpro (&xd_registered_buses); |
| 2146 | staticpro (&xd_registered_inhibitor_locks); | 2168 | staticpro (&xd_registered_fds); |
| 2147 | 2169 | ||
| 2148 | Fprovide (intern_c_string ("dbusbind"), Qnil); | 2170 | Fprovide (intern_c_string ("dbusbind"), Qnil); |
| 2149 | } | 2171 | } |
diff --git a/test/lisp/net/dbus-tests.el b/test/lisp/net/dbus-tests.el index 53ce1929cad..f4dd9e3796b 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el | |||
| @@ -2308,89 +2308,156 @@ The argument EXPECTED-ARGS is a list of expected arguments for the method." | |||
| 2308 | ;; Cleanup. | 2308 | ;; Cleanup. |
| 2309 | (dbus-unregister-service :session dbus--test-service))) | 2309 | (dbus-unregister-service :session dbus--test-service))) |
| 2310 | 2310 | ||
| 2311 | (ert-deftest dbus-test10-inhibitor-locks () | 2311 | (ert-deftest dbus-test10-keep-fd () |
| 2312 | "Check `dbus-*-inhibitor-locks'." | 2312 | "Check D-Bus `:keep-fd' argument." |
| 2313 | :tags '(:expensive-test) | 2313 | :tags '(:expensive-test) |
| 2314 | (skip-unless dbus--test-enabled-system-bus) | 2314 | (skip-unless dbus--test-enabled-system-bus) |
| 2315 | (skip-unless (dbus-ping :system dbus--test-systemd-service 1000)) | 2315 | (skip-unless (dbus-ping :system dbus--test-systemd-service 1000)) |
| 2316 | 2316 | ||
| 2317 | (let (lock1 lock2) | 2317 | (let ((what "sleep") |
| 2318 | (who "Emacs test user") | ||
| 2319 | (why "Test delay") | ||
| 2320 | (mode "delay") | ||
| 2321 | (fd-directory (format "/proc/%d/fd" (emacs-pid))) | ||
| 2322 | lock1 lock2) | ||
| 2318 | ;; Create inhibitor lock. | 2323 | ;; Create inhibitor lock. |
| 2319 | (setq lock1 (dbus-make-inhibitor-lock "sleep" "Test delay")) | 2324 | (setq lock1 |
| 2325 | (dbus-call-method | ||
| 2326 | :system dbus--test-systemd-service dbus--test-systemd-path | ||
| 2327 | dbus--test-systemd-manager-interface "Inhibit" | ||
| 2328 | what who why mode)) | ||
| 2320 | (should (natnump lock1)) | 2329 | (should (natnump lock1)) |
| 2321 | ;; The lock is reported by systemd. | 2330 | ;; The lock is reported by systemd. |
| 2322 | (should | 2331 | (should |
| 2323 | (member | 2332 | (member |
| 2324 | (list "sleep" "Emacs" "Test delay" "delay" (user-uid) (emacs-pid)) | 2333 | (list what who why mode (user-uid) (emacs-pid)) |
| 2325 | (dbus-call-method | 2334 | (dbus-call-method |
| 2326 | :system dbus--test-systemd-service dbus--test-systemd-path | 2335 | :system dbus--test-systemd-service dbus--test-systemd-path |
| 2327 | dbus--test-systemd-manager-interface "ListInhibitors"))) | 2336 | dbus--test-systemd-manager-interface "ListInhibitors"))) |
| 2328 | ;; The lock is registered internally. | 2337 | ;; The lock is not registered internally. |
| 2329 | (should | 2338 | (should-not (assoc lock1 (dbus--registered-fds))) |
| 2330 | (member | ||
| 2331 | (list lock1 "sleep" "Test delay" nil) | ||
| 2332 | (dbus-registered-inhibitor-locks))) | ||
| 2333 | ;; There exist a file descriptor. | 2339 | ;; There exist a file descriptor. |
| 2334 | (when (file-directory-p (format "/proc/%d/fd" (emacs-pid))) | 2340 | (when (file-directory-p fd-directory) |
| 2335 | (should (file-symlink-p (format "/proc/%d/fd/%d" (emacs-pid) lock1)))) | 2341 | (should |
| 2336 | 2342 | (file-symlink-p | |
| 2337 | ;; It is not possible to modify registered inhibitor locks on Lisp level. | 2343 | (expand-file-name (number-to-string lock1) fd-directory)))) |
| 2338 | (setcar (assoc lock1 (dbus-registered-inhibitor-locks)) 'malicious) | ||
| 2339 | (should (assoc lock1 (dbus-registered-inhibitor-locks))) | ||
| 2340 | (should-not (assoc 'malicious (dbus-registered-inhibitor-locks))) | ||
| 2341 | |||
| 2342 | ;; Creating it again returns the same inhibitor lock. | ||
| 2343 | (should (= lock1 (dbus-make-inhibitor-lock "sleep" "Test delay"))) | ||
| 2344 | 2344 | ||
| 2345 | ;; Create another inhibitor lock. | 2345 | ;; Create another inhibitor lock. Keep the file descriptor. |
| 2346 | (setq lock2 (dbus-make-inhibitor-lock "sleep" "Test block" 'block)) | 2346 | (setq lock2 |
| 2347 | (dbus-call-method | ||
| 2348 | :system dbus--test-systemd-service dbus--test-systemd-path | ||
| 2349 | dbus--test-systemd-manager-interface "Inhibit" :keep-fd | ||
| 2350 | what who why mode)) | ||
| 2347 | (should (natnump lock2)) | 2351 | (should (natnump lock2)) |
| 2348 | (should-not (= lock1 lock2)) | 2352 | (should-not (= lock1 lock2)) |
| 2349 | ;; The lock is reported by systemd. | 2353 | ;; The lock is reported by systemd. |
| 2350 | (should | 2354 | (should |
| 2351 | (member | 2355 | (member |
| 2352 | (list "sleep" "Emacs" "Test block" "block" (user-uid) (emacs-pid)) | 2356 | (list what who why mode (user-uid) (emacs-pid)) |
| 2353 | (dbus-call-method | 2357 | (dbus-call-method |
| 2354 | :system dbus--test-systemd-service dbus--test-systemd-path | 2358 | :system dbus--test-systemd-service dbus--test-systemd-path |
| 2355 | dbus--test-systemd-manager-interface "ListInhibitors"))) | 2359 | dbus--test-systemd-manager-interface "ListInhibitors"))) |
| 2356 | ;; The lock is registered internally. | 2360 | ;; The lock is registered internally. |
| 2357 | (should | 2361 | (should |
| 2358 | (member | 2362 | (member |
| 2359 | (list lock2 "sleep" "Test block" t) | 2363 | (cons lock2 dbus--test-systemd-path) |
| 2360 | (dbus-registered-inhibitor-locks))) | 2364 | (dbus--registered-fds))) |
| 2361 | ;; There exist a file descriptor. | 2365 | ;; There exist a file descriptor. |
| 2362 | (when (file-directory-p (format "/proc/%d/fd" (emacs-pid))) | 2366 | (when (file-directory-p fd-directory) |
| 2363 | (should (file-symlink-p (format "/proc/%d/fd/%d" (emacs-pid) lock2)))) | 2367 | (should |
| 2364 | 2368 | (file-symlink-p | |
| 2365 | ;; Close the first inhibitor lock. | 2369 | (expand-file-name (number-to-string lock2) fd-directory)))) |
| 2366 | (should (dbus-close-inhibitor-lock lock1)) | 2370 | |
| 2367 | ;; The internal registration has gone. | 2371 | ;; Create another inhibitor lock via |
| 2368 | (should-not | 2372 | ;; `dbus-call-method-asynchronously'. Keep the file descriptor. |
| 2369 | (member | 2373 | (setq lock1 nil) |
| 2370 | (list lock1 "sleep" "Test delay" nil) | 2374 | (dbus-call-method-asynchronously |
| 2371 | (dbus-registered-inhibitor-locks))) | 2375 | :system dbus--test-systemd-service dbus--test-systemd-path |
| 2372 | ;; The file descriptor has been deleted. | 2376 | dbus--test-systemd-manager-interface "Inhibit" |
| 2373 | (when (file-directory-p (format "/proc/%d/fd" (emacs-pid))) | 2377 | (lambda (lock) (setq lock1 lock)) :keep-fd |
| 2374 | (should-not (file-symlink-p (format "/proc/%d/fd/%d" (emacs-pid) lock1)))) | 2378 | what who why mode) |
| 2375 | 2379 | (with-timeout (1 (dbus--test-timeout-handler)) | |
| 2376 | ;; Closing it again is a noop. | 2380 | (while (null lock1) (read-event nil nil 0.1))) |
| 2377 | (should-not (dbus-close-inhibitor-lock lock1)) | ||
| 2378 | |||
| 2379 | ;; Creating it again returns (another?) inhibitor lock. | ||
| 2380 | (setq lock1 (dbus-make-inhibitor-lock "sleep" "Test delay")) | ||
| 2381 | (should (natnump lock1)) | 2381 | (should (natnump lock1)) |
| 2382 | (should-not (= lock1 lock2)) | ||
| 2382 | ;; The lock is registered internally. | 2383 | ;; The lock is registered internally. |
| 2383 | (should | 2384 | (should |
| 2384 | (member | 2385 | (member |
| 2385 | (list lock1 "sleep" "Test delay" nil) | 2386 | (cons lock1 dbus--test-systemd-path) |
| 2386 | (dbus-registered-inhibitor-locks))) | 2387 | (dbus--registered-fds))) |
| 2387 | ;; There exist a file descriptor. | 2388 | ;; There exist a file descriptor. |
| 2388 | (when (file-directory-p (format "/proc/%d/fd" (emacs-pid))) | 2389 | (when (file-directory-p fd-directory) |
| 2389 | (should (file-symlink-p (format "/proc/%d/fd/%d" (emacs-pid) lock1)))) | 2390 | (should |
| 2391 | (file-symlink-p | ||
| 2392 | (expand-file-name (number-to-string lock1) fd-directory)))) | ||
| 2393 | |||
| 2394 | ;; It is not possible to modify registered inhibitor locks on Lisp level. | ||
| 2395 | (setcar (assoc lock1 (dbus--registered-fds)) 'malicious) | ||
| 2396 | (should (assoc lock1 (dbus--registered-fds))) | ||
| 2397 | (should-not (assoc 'malicious (dbus--registered-fds))) | ||
| 2390 | 2398 | ||
| 2391 | ;; Close the inhibitor locks. | 2399 | ;; Close the inhibitor locks. |
| 2392 | (should (dbus-close-inhibitor-lock lock1)) | 2400 | (should (dbus--fd-close lock1)) |
| 2393 | (should (dbus-close-inhibitor-lock lock2)))) | 2401 | (should (dbus--fd-close lock2)) |
| 2402 | ;; The internal registration has gone. | ||
| 2403 | (should-not | ||
| 2404 | (member | ||
| 2405 | (cons lock1 dbus--test-systemd-path) | ||
| 2406 | (dbus--registered-fds))) | ||
| 2407 | (should-not | ||
| 2408 | (member | ||
| 2409 | (cons lock2 dbus--test-systemd-path) | ||
| 2410 | (dbus--registered-fds))) | ||
| 2411 | ;; The file descriptors have been deleted. | ||
| 2412 | (when (file-directory-p fd-directory) | ||
| 2413 | (should-not | ||
| 2414 | (file-exists-p (expand-file-name (number-to-string lock1) fd-directory))) | ||
| 2415 | (should-not | ||
| 2416 | (file-exists-p (expand-file-name (number-to-string lock2) fd-directory)))) | ||
| 2417 | |||
| 2418 | ;; Closing them again is a noop. | ||
| 2419 | (should-not (dbus--fd-close lock1)) | ||
| 2420 | (should-not (dbus--fd-close lock2)))) | ||
| 2421 | |||
| 2422 | (ert-deftest dbus-test10-open-close-fd () | ||
| 2423 | "Check D-Bus open/close a file descriptor." | ||
| 2424 | :tags '(:expensive-test) | ||
| 2425 | (skip-unless dbus--test-enabled-system-bus) | ||
| 2426 | (skip-unless (dbus-ping :system dbus--test-systemd-service 1000)) | ||
| 2427 | |||
| 2428 | (ert-with-temp-file tmpfile | ||
| 2429 | (let ((fd-directory (format "/proc/%d/fd" (emacs-pid))) | ||
| 2430 | fd) | ||
| 2431 | ;; Create file descriptor. | ||
| 2432 | (setq fd (dbus--fd-open tmpfile)) | ||
| 2433 | (should (natnump fd)) | ||
| 2434 | ;; The file descriptor is registered internally. | ||
| 2435 | (should (member (cons fd tmpfile) (dbus--registered-fds))) | ||
| 2436 | ;; There exist a file descriptor file. | ||
| 2437 | (when (file-directory-p fd-directory) | ||
| 2438 | (should | ||
| 2439 | (file-symlink-p (expand-file-name (number-to-string fd) fd-directory))) | ||
| 2440 | (should | ||
| 2441 | (string-equal | ||
| 2442 | (file-truename (expand-file-name (number-to-string fd) fd-directory)) | ||
| 2443 | tmpfile))) | ||
| 2444 | |||
| 2445 | ;; It is not possible to modify registered file descriptors on Lisp level. | ||
| 2446 | (setcar (assoc fd (dbus--registered-fds)) 'malicious) | ||
| 2447 | (should (assoc fd (dbus--registered-fds))) | ||
| 2448 | (should-not (assoc 'malicious (dbus--registered-fds))) | ||
| 2449 | |||
| 2450 | ;; Close the file descriptor. | ||
| 2451 | (should (dbus--fd-close fd)) | ||
| 2452 | ;; The internal registration has gone. | ||
| 2453 | (should-not (member (cons fd tmpfile) (dbus--registered-fds))) | ||
| 2454 | ;; The file descriptor file has been deleted. | ||
| 2455 | (when (file-directory-p fd-directory) | ||
| 2456 | (should-not | ||
| 2457 | (file-exists-p (expand-file-name (number-to-string fd) fd-directory)))) | ||
| 2458 | |||
| 2459 | ;; Closing it again is a noop. | ||
| 2460 | (should-not (dbus--fd-close fd))))) | ||
| 2394 | 2461 | ||
| 2395 | (defun dbus-test-all (&optional interactive) | 2462 | (defun dbus-test-all (&optional interactive) |
| 2396 | "Run all tests for \\[dbus]." | 2463 | "Run all tests for \\[dbus]." |