GNU bug report logs - #79963
No way to close file descriptors (gnus bug involving dbus and sleep)

Previous Next

Package: emacs;

Reported by: Morgan Smith <Morgan.J.Smith <at> outlook.com>

Date: Sun, 7 Dec 2025 21:19:01 UTC

Severity: normal

To reply to this bug, email your comments to 79963 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#79963; Package emacs. (Sun, 07 Dec 2025 21:19:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Morgan Smith <Morgan.J.Smith <at> outlook.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Sun, 07 Dec 2025 21:19:01 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Morgan Smith <Morgan.J.Smith <at> outlook.com>
To: bug-gnu-emacs <at> gnu.org
Cc: eric <at> ericabrahamsen.net
Subject: No way to close file descriptors (gnus bug involving dbus and sleep)
Date: Sun, 07 Dec 2025 16:12:56 -0500
As far as I can tell there is no way for user code to close a file descriptor
that emacs owns (found in "/proc/(emacs-pid)/fd/#").

You're probably curious as to why the heck I would want to do that.  Well the
answer involves dbus, sleep, and a bug in gnus.

Gnus has an option `gnus-dbus-close-on-sleep' which will run
#'gnus-dbus-sleep-handler when emacs receives the dbus signal
"PrepareForSleep".  Unfortunatly, gnus often doesn't get to finish executing
this function before sleep starts as the system doesn't know to wait for gnus.

What gnus should be doing is creating a sleep inhibitor with a mode of "delay".
Then after gnus is done reacting to the "PrepareForSleep" signal, it should
release the inhibitor, which is done by closing a file descriptor.

Please see the following code which illistrates what should be done up until
the end where it fails and I'm not sure what the fix is.

Also I'd like to note that I don't really care that deeply about this
gnus bug.  I'm simply trying to create my own custom functions that run
before sleep.

#+begin_src elisp
(let* ((unix-file-descriptor
       (dbus-call-method
       :system
       "org.freedesktop.login1"
       "/org/freedesktop/login1"
       "org.freedesktop.login1.Manager"
       "Inhibit"
       "sleep:shutdown" ;; what
       "emacs" ;; who
       "gnus-cleanup" ;; why
       "delay" ;; mode
       ))
       (inhibit-file
        (concat
         "/proc/" (number-to-string (emacs-pid)) "/fd/" (number-to-string fd)))
  ;; Looks like this really is the inhibitor file descriptor
  (file-attribute-type (file-attributes inhibit-file))
  ;; => "/run/systemd/inhibit/1033.ref"
  
  ;; Then we wait for "PrepareForSleep" signal.

  ;; Once we get the signal we do our cleanup:
  (our-cleanup-function)
    
  ;; How do I close the file descriptor?
  ;; This returns permission denied:
  (shell-command-to-string
   (concat "exec /proc/" (number-to-string (emacs-pid)) "/fd/" (number-to-string fd) ">&-")))
#+end_src




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79963; Package emacs. (Sun, 07 Dec 2025 22:39:01 GMT) Full text and rfc822 format available.

Message #8 received at 79963 <at> debbugs.gnu.org (full text, mbox):

From: Andreas Schwab <schwab <at> linux-m68k.org>
To: Morgan Smith <Morgan.J.Smith <at> outlook.com>
Cc: eric <at> ericabrahamsen.net, 79963 <at> debbugs.gnu.org
Subject: Re: bug#79963: No way to close file descriptors (gnus bug involving
 dbus and sleep)
Date: Sun, 07 Dec 2025 23:37:53 +0100
On Dez 07 2025, Morgan Smith wrote:

> (let* ((unix-file-descriptor
>        (dbus-call-method
>        :system
>        "org.freedesktop.login1"
>        "/org/freedesktop/login1"
>        "org.freedesktop.login1.Manager"
>        "Inhibit"
>        "sleep:shutdown" ;; what
>        "emacs" ;; who
>        "gnus-cleanup" ;; why
>        "delay" ;; mode
>        ))
>        (inhibit-file
>         (concat
>          "/proc/" (number-to-string (emacs-pid)) "/fd/" (number-to-string fd)))

What is fd?  Where does it come from?

-- 
Andreas Schwab, schwab <at> linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79963; Package emacs. (Mon, 08 Dec 2025 00:25:02 GMT) Full text and rfc822 format available.

Message #11 received at 79963 <at> debbugs.gnu.org (full text, mbox):

From: Morgan Smith <morgan.j.smith <at> outlook.com>
To: Andreas Schwab <schwab <at> linux-m68k.org>
Cc: eric <at> ericabrahamsen.net, 79963 <at> debbugs.gnu.org
Subject: Re: bug#79963: No way to close file descriptors (gnus bug involving
 dbus and sleep)
Date: Sun, 07 Dec 2025 19:24:09 -0500
Andreas Schwab <schwab <at> linux-m68k.org> writes:
>
> What is fd?  Where does it come from?

Sorry.  Here is a "working" code snippet.

#+begin_src elisp
(let* ((unix-file-descriptor
        (dbus-call-method
         :system
         "org.freedesktop.login1"
         "/org/freedesktop/login1"
         "org.freedesktop.login1.Manager"
         "Inhibit"
         "sleep:shutdown" ;; what
         "emacs" ;; who
         "gnus-cleanup" ;; why
         "delay" ;; mode
         ))
       (inhibit-file
        (concat
         "/proc/" (number-to-string (emacs-pid)) "/fd/" (number-to-string unix-file-descriptor))))
       ;; Looks like this really is the inhibitor file descriptor
       (file-attribute-type (file-attributes inhibit-file))
       ;; => "/run/systemd/inhibit/1033.ref"
       
       ;; Then we wait for "PrepareForSleep" signal.

       ;; Once we get the signal we do our cleanup:
       (gnus-dbus-sleep-handler t)
       
       ;; How do I close the file descriptor?
       ;; This returns permission denied:
       (shell-command-to-string
        (concat "exec " inhibit-file ">&-")))
#+end_src

#+RESULTS:
: /gnu/store/p5dap5q3wfdy0h3m31q5hbj3gpbkmrxv-bash-5.2.37/bin/bash: line 1: /proc/1196/fd/31: Permission denied
: /gnu/store/p5dap5q3wfdy0h3m31q5hbj3gpbkmrxv-bash-5.2.37/bin/bash: line 1: exec: /proc/1196/fd/31: cannot execute: Permission denied




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79963; Package emacs. (Mon, 08 Dec 2025 11:33:01 GMT) Full text and rfc822 format available.

Message #14 received at 79963 <at> debbugs.gnu.org (full text, mbox):

From: Michael Albinus <michael.albinus <at> gmx.de>
To: Morgan Smith <morgan.j.smith <at> outlook.com>
Cc: eric <at> ericabrahamsen.net, Andreas Schwab <schwab <at> linux-m68k.org>,
 79963 <at> debbugs.gnu.org
Subject: Re: bug#79963: No way to close file descriptors (gnus bug involving
 dbus and sleep)
Date: Mon, 08 Dec 2025 12:32:16 +0100
Morgan Smith <morgan.j.smith <at> outlook.com> writes:

Hi Morgan,

> #+begin_src elisp
> (let* ((unix-file-descriptor
>         (dbus-call-method
>          :system
>          "org.freedesktop.login1"
>          "/org/freedesktop/login1"
>          "org.freedesktop.login1.Manager"
>          "Inhibit"
>          "sleep:shutdown" ;; what
>          "emacs" ;; who
>          "gnus-cleanup" ;; why
>          "delay" ;; mode
>          ))
>        (inhibit-file
>         (concat
>          "/proc/" (number-to-string (emacs-pid)) "/fd/" (number-to-string unix-file-descriptor))))
>        ;; Looks like this really is the inhibitor file descriptor
>        (file-attribute-type (file-attributes inhibit-file))
>        ;; => "/run/systemd/inhibit/1033.ref"
>        
>        ;; Then we wait for "PrepareForSleep" signal.
>
>        ;; Once we get the signal we do our cleanup:
>        (gnus-dbus-sleep-handler t)
>        
>        ;; How do I close the file descriptor?
>        ;; This returns permission denied:
>        (shell-command-to-string
>         (concat "exec " inhibit-file ">&-")))
> #+end_src

On <https://systemd.io/INHIBITOR_LOCKS/>, there is

--8<---------------cut here---------------start------------->8---
Inhibit() returns a single value, a file descriptor that encapsulates
the lock. As soon as the file descriptor is closed (and all its
duplicates) the lock is automatically released. If the client dies while
the lock is taken the kernel automatically closes the file descriptor so
that the lock is automatically released.
--8<---------------cut here---------------end--------------->8---

Wouldn't it be sufficient to close the D-Bus connection? That is, call
something like (dbus-close-bus :system) .

We don't have such a Lisp function yet. But the code is already in
dbusbind.c, see

--8<---------------cut here---------------start------------->8---
/* Close connection to D-Bus BUS.  */
static void
xd_close_bus (Lisp_Object bus)
--8<---------------cut here---------------end--------------->8---

Perhaps we shall offer this function in Lisp?

Alternatively, you might try (dbus--init-bus :system) . This calls by
side effect

--8<---------------cut here---------------start------------->8---
  /* Close bus if it is already open.  */
  xd_close_bus (bus);
--8<---------------cut here---------------end--------------->8---

Best regards, Michael.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79963; Package emacs. (Mon, 08 Dec 2025 11:47:01 GMT) Full text and rfc822 format available.

Message #17 received at 79963 <at> debbugs.gnu.org (full text, mbox):

From: Stéphane Marks <shipmints <at> gmail.com>
To: Michael Albinus <michael.albinus <at> gmx.de>
Cc: eric <at> ericabrahamsen.net, Morgan Smith <morgan.j.smith <at> outlook.com>,
 Andrew Cohen <acohen <at> ust.hk>, Andreas Schwab <schwab <at> linux-m68k.org>,
 79963 <at> debbugs.gnu.org
Subject: Re: bug#79963: No way to close file descriptors (gnus bug involving
 dbus and sleep)
Date: Mon, 8 Dec 2025 06:45:51 -0500
[Message part 1 (text/plain, inline)]
On Mon, Dec 8, 2025 at 6:33 AM Michael Albinus via Bug reports for GNU
Emacs, the Swiss army knife of text editors <bug-gnu-emacs <at> gnu.org> wrote:

> Morgan Smith <morgan.j.smith <at> outlook.com> writes:
>
> Hi Morgan,
>
> > #+begin_src elisp
> > (let* ((unix-file-descriptor
> >         (dbus-call-method
> >          :system
> >          "org.freedesktop.login1"
> >          "/org/freedesktop/login1"
> >          "org.freedesktop.login1.Manager"
> >          "Inhibit"
> >          "sleep:shutdown" ;; what
> >          "emacs" ;; who
> >          "gnus-cleanup" ;; why
> >          "delay" ;; mode
> >          ))
> >        (inhibit-file
> >         (concat
> >          "/proc/" (number-to-string (emacs-pid)) "/fd/"
> (number-to-string unix-file-descriptor))))
> >        ;; Looks like this really is the inhibitor file descriptor
> >        (file-attribute-type (file-attributes inhibit-file))
> >        ;; => "/run/systemd/inhibit/1033.ref"
> >
> >        ;; Then we wait for "PrepareForSleep" signal.
> >
> >        ;; Once we get the signal we do our cleanup:
> >        (gnus-dbus-sleep-handler t)
> >
> >        ;; How do I close the file descriptor?
> >        ;; This returns permission denied:
> >        (shell-command-to-string
> >         (concat "exec " inhibit-file ">&-")))
> > #+end_src
>
> On <https://systemd.io/INHIBITOR_LOCKS/>, there is
>
> --8<---------------cut here---------------start------------->8---
> Inhibit() returns a single value, a file descriptor that encapsulates
> the lock. As soon as the file descriptor is closed (and all its
> duplicates) the lock is automatically released. If the client dies while
> the lock is taken the kernel automatically closes the file descriptor so
> that the lock is automatically released.
> --8<---------------cut here---------------end--------------->8---
>
> Wouldn't it be sufficient to close the D-Bus connection? That is, call
> something like (dbus-close-bus :system) .
>
> We don't have such a Lisp function yet. But the code is already in
> dbusbind.c, see
>
> --8<---------------cut here---------------start------------->8---
> /* Close connection to D-Bus BUS.  */
> static void
> xd_close_bus (Lisp_Object bus)
> --8<---------------cut here---------------end--------------->8---
>
> Perhaps we shall offer this function in Lisp?
>
> Alternatively, you might try (dbus--init-bus :system) . This calls by
> side effect
>
> --8<---------------cut here---------------start------------->8---
>   /* Close bus if it is already open.  */
>   xd_close_bus (bus);
> --8<---------------cut here---------------end--------------->8---
>

This would be ideal.  The implementation of a system-sleep-wake interface
that I worked on with Andrew Cohen needs this, as it also uses a D-Bus
inhibitor.  The prototype resorted to scanning the proc file system (which
exists only on systems that support it) and then invoking a hacked
descriptor closer function.  We could rekindle that work with your proposed
function.
[Message part 2 (text/html, inline)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79963; Package emacs. (Mon, 08 Dec 2025 14:18:02 GMT) Full text and rfc822 format available.

Message #20 received at 79963 <at> debbugs.gnu.org (full text, mbox):

From: Michael Albinus <michael.albinus <at> gmx.de>
To: Stéphane Marks <shipmints <at> gmail.com>
Cc: eric <at> ericabrahamsen.net, Morgan Smith <morgan.j.smith <at> outlook.com>,
 Andrew Cohen <acohen <at> ust.hk>, Andreas Schwab <schwab <at> linux-m68k.org>,
 79963 <at> debbugs.gnu.org
Subject: Re: bug#79963: No way to close file descriptors (gnus bug involving
 dbus and sleep)
Date: Mon, 08 Dec 2025 15:17:03 +0100
[Message part 1 (text/plain, inline)]
Stéphane Marks <shipmints <at> gmail.com> writes:

Hi,

>     Wouldn't it be sufficient to close the D-Bus connection? That is,
>     call
>     something like (dbus-close-bus :system) .
>
>     We don't have such a Lisp function yet. But the code is already in
>     dbusbind.c, see
>
>     --8<---------------cut here---------------start------------->8---
>     /* Close connection to D-Bus BUS.  */
>     static void
>     xd_close_bus (Lisp_Object bus)
>     --8<---------------cut here---------------end--------------->8---
>
>     Perhaps we shall offer this function in Lisp?
>
> This would be ideal.  The implementation of a system-sleep-wake
> interface that I worked on with Andrew Cohen needs this, as it also
> uses a D-Bus inhibitor.  The prototype resorted to scanning the proc
> file system (which exists only on systems that support it) and then
> invoking a hacked descriptor closer function.  We could rekindle that
> work with your proposed function.

Please try the appended patch. Since there could be several connection
references, you should call like

--8<---------------cut here---------------start------------->8---
(while (not (zerop (dbus--close-bus :system))))
--8<---------------cut here---------------end--------------->8---

Best regards, Michael.

[Message part 2 (text/x-patch, attachment)]

This bug report was last modified 2 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.