GNU bug report logs - #78757
shepherd: dangling file descriptor to /dev/console

Previous Next

Package: guix;

Reported by: burban <at> opopop.net

Date: Wed, 11 Jun 2025 14:55:02 UTC

Severity: normal

Done: Ludovic Courtès <ludo <at> gnu.org>

To reply to this bug, email your comments to 78757 AT debbugs.gnu.org.
There is no need to reopen the bug first.

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-guix <at> gnu.org:
bug#78757; Package guix. (Wed, 11 Jun 2025 14:55:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to burban <at> opopop.net:
New bug report received and forwarded. Copy sent to bug-guix <at> gnu.org. (Wed, 11 Jun 2025 14:55:02 GMT) Full text and rfc822 format available.

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

From: burban <at> opopop.net
To: bug-guix <at> gnu.org
Subject: shepherd: dangling file descriptor to /dev/console
Date: Tue, 10 Jun 2025 20:31:51 +0000
Hello,

All shepherd children have an open file descriptor to /dev/console,
probably because of the use of dup2 (and not dup3) in system.scm.

The pb. disapears if I force that flag with that code before I define
my services (context: shepherd used as init system on Debian):
(port-for-each (lambda (x)
                 (catch #t
		   (lambda ()
		     (when (= (fcntl x F_GETFD) 0)
		       (fcntl x F_SETFD FD_CLOEXEC)
		       (format #t "FD_CLOEXEC flag set on port ~a (fd: ~a)\n" x (port->fdes x))))
		   (lambda (keys . args) (format #t "fcntl error for port ~a\n" x)))
		 ))


Sincerely.

-- 

Bernard





Information forwarded to bug-guix <at> gnu.org:
bug#78757; Package guix. (Fri, 13 Jun 2025 22:54:02 GMT) Full text and rfc822 format available.

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

From: Ludovic Courtès <ludo <at> gnu.org>
To: 78757 <at> debbugs.gnu.org,  burban <at> opopop.net
Subject: Re: bug#78757: shepherd: dangling file descriptor to /dev/console
Date: Sat, 14 Jun 2025 00:47:56 +0200
Hi burban,

burban--- via Bug reports for GNU Guix <bug-guix <at> gnu.org> writes:

> All shepherd children have an open file descriptor to /dev/console,
> probably because of the use of dup2 (and not dup3) in system.scm.

I checked the /proc/PID/fd directory of several of my system services on
Guix System (nscd, guix-publish, ntpd, upower-daemon) and I don’t see
any file descriptor pointing to /dev/console, with version 1.0.5.

You said you’re on Debian; which version of the Shepherd is it?

I also don’t see any ‘dup2’ call in ‘system.scm’; this takes place
rather in ‘service.scm’.

> The pb. disapears if I force that flag with that code before I define
> my services (context: shepherd used as init system on Debian):
> (port-for-each (lambda (x)
>                  (catch #t
> 		   (lambda ()
> 		     (when (= (fcntl x F_GETFD) 0)
> 		       (fcntl x F_SETFD FD_CLOEXEC)
> 		       (format #t "FD_CLOEXEC flag set on port ~a (fd: ~a)\n" x (port->fdes x))))
> 		   (lambda (keys . args) (format #t "fcntl error for port ~a\n" x)))
> 		 ))

‘shepherd’ marks all previously-opened FDs as O_CLOEXEC upfront—see
‘mark-as-close-on-exec’ in ‘shepherd.scm’.  Those opened later are
opened with O_CLOEXEC, except for user code that explicitly omits the
O_CLOEXEC flag.

Thanks,
Ludo’.




Information forwarded to bug-guix <at> gnu.org:
bug#78757; Package guix. (Sun, 15 Jun 2025 06:59:06 GMT) Full text and rfc822 format available.

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

From: burban <at> opopop.net
To: Ludovic Courtès <ludo <at> gnu.org>
Cc: 78757 <at> debbugs.gnu.org
Subject: Re: bug#78757: shepherd: dangling file descriptor to /dev/console
Date: Sat, 14 Jun 2025 20:22:11 +0000
Hello,

Ludovic Courtès <ludo <at> gnu.org> writes:

> Hi burban,
>
> burban--- via Bug reports for GNU Guix <bug-guix <at> gnu.org> writes:
>
>> All shepherd children have an open file descriptor to /dev/console,
>> probably because of the use of dup2 (and not dup3) in system.scm.
>
> I checked the /proc/PID/fd directory of several of my system services on
> Guix System (nscd, guix-publish, ntpd, upower-daemon) and I don’t see
> any file descriptor pointing to /dev/console, with version 1.0.5.
>
> You said you’re on Debian; which version of the Shepherd is it?

Bookworm with my own shepherd package (1.0.0) and also Trixie with the
official shepherd package (1.0.3).

Without the CLOEXEC forcing below, I get this:

# lsof |grep shepherd |grep /dev/console
shepherd       1                         root    0u      CHR                5,1      0t0         12 /dev/console
shepherd       1                         root    1u      CHR                5,1      0t0         12 /dev/console
shepherd       1                         root    2u      CHR                5,1      0t0         12 /dev/console
shepherd       1                         root   19w      CHR                5,1      0t0         12 /dev/console
shepherd       1    183 shepherd         root    0u      CHR                5,1      0t0         12 /dev/console
shepherd       1    183 shepherd         root    1u      CHR                5,1      0t0         12 /dev/console
shepherd       1    183 shepherd         root    2u      CHR                5,1      0t0         12 /dev/console
shepherd       1    183 shepherd         root   19w      CHR                5,1      0t0         12 /dev/console
shepherd       1 251476 shepherd         root    0u      CHR                5,1      0t0         12 /dev/console
shepherd       1 251476 shepherd         root    1u      CHR                5,1      0t0         12 /dev/console
shepherd       1 251476 shepherd         root    2u      CHR                5,1      0t0         12 /dev/console
shepherd       1 251476 shepherd         root   19w      CHR                5,1      0t0         12 /dev/console

and fd 19 is duplicated for a lot of the children:

# lsof |grep 19w
systemd-u    211                         root   19w      CHR                5,1      0t0         12 /dev/console
getty        853                         root   19w      CHR                5,1      0t0         12 /dev/console
getty        856                         root   19w      CHR                5,1      0t0         12 /dev/console
getty        859                         root   19w      CHR                5,1      0t0         12 /dev/console
radvd        894                        radvd   19w      CHR                5,1      0t0         12 /dev/console
radvd        895                         root   19w      CHR                5,1      0t0         12 /dev/console
exim4       1001                  Debian-exim   19w      CHR                5,1      0t0         12 /dev/console
ntpd        1003                       ntpsec   19w      CHR                5,1      0t0         12 /dev/console
fwknopd     1005                         root   19w      CHR                5,1      0t0         12 /dev/console
dbus-daem   1006                   messagebus   19w      CHR                5,1      0t0         12 /dev/console
openvpn     1416                         root   19w      CHR                5,1      0t0         12 /dev/console
apache2   160524                         root   19w      CHR                5,1      0t0         12 /dev/console
php-fpm8. 160561                         root   19w      CHR                5,1      0t0         12 /dev/console
php-fpm8. 160562                     www-data   19w      CHR                5,1      0t0         12 /dev/console
php-fpm8. 160563                     www-data   19w      CHR                5,1      0t0         12 /dev/console
unbound   199459                      unbound   19w      CHR                5,1      0t0         12 /dev/console
postgres  214913                     postgres   19w      CHR                5,1      0t0         12 /dev/console
cron      230165                         root   19w      CHR                5,1      0t0         12 /dev/console
apache2   281804                     www-data   19w      CHR                5,1      0t0         12 /dev/console
apache2   281804 281805 apache2      www-data   19w      CHR                5,1      0t0         12 /dev/console

And here the boot log when forcing CLOEXEC:

2025-06-13T11:32:51.657288+02:00 tanis [    8.21    ] shepherd[1]: fcntl error for port #<output:soft-port 7f4045fb2980>
2025-06-13T11:32:51.657312+02:00 tanis [    8.21    ] shepherd[1]: FD_CLOEXEC flag set on port #<output: file /dev/console> (fd: 2)
2025-06-13T11:32:51.657336+02:00 tanis [    8.21    ] shepherd[1]: FD_CLOEXEC flag set on port #<output: file /dev/console> (fd: 1)
2025-06-13T11:32:51.657359+02:00 tanis [    8.22    ] shepherd[1]: fcntl error for port #<output: #{write pipe}# 24>
2025-06-13T11:32:51.657383+02:00 tanis [    8.22    ] shepherd[1]: FD_CLOEXEC flag set on port #<output: /proc/self/fd/1 /dev/console> (fd: 19)
2025-06-13T11:32:51.657408+02:00 tanis [    8.22    ] shepherd[1]: fcntl error for port #<output: #{write pipe}# 24>
2025-06-13T11:32:51.657432+02:00 tanis [    8.22    ] shepherd[1]: FD_CLOEXEC flag set on port #<input: file /dev/console> (fd: 0)
2025-06-13T11:32:51.657456+02:00 tanis [    8.234859] shepherd[1]: GNU Shepherd 1.0.3 (Guile 3.0.10, x86_64-pc-linux-gnu)
2025-06-13T11:32:51.657480+02:00 tanis [    8.234924] shepherd[1]: Starting service root...
2025-06-13T11:32:51.657503+02:00 tanis [    8.235127] shepherd[1]: Service root started.
 
> I also don’t see any ‘dup2’ call in ‘system.scm’; this takes place
> rather in ‘service.scm’.

Oops, yes of course.

>> The pb. disapears if I force that flag with that code before I define
>> my services (context: shepherd used as init system on Debian):
>> (port-for-each (lambda (x)
>>                  (catch #t
>> 		   (lambda ()
>> 		     (when (= (fcntl x F_GETFD) 0)
>> 		       (fcntl x F_SETFD FD_CLOEXEC)
>> 		       (format #t "FD_CLOEXEC flag set on port ~a (fd: ~a)\n" x (port->fdes x))))
>> 		   (lambda (keys . args) (format #t "fcntl error for port ~a\n" x)))
>> 		 ))
>
> ‘shepherd’ marks all previously-opened FDs as O_CLOEXEC upfront—see
> ‘mark-as-close-on-exec’ in ‘shepherd.scm’.  Those opened later are
> opened with O_CLOEXEC, except for user code that explicitly omits the
> O_CLOEXEC flag.

Hmmm.... I have at one point (before the above (port-for-each ...)

(define *s* (open-output-file "/proc/self/fd/1"))

to have an early log output to (on ordinary PC) /dev/tty1. But maybe /dev/tty1
is a synonym for /dev/console. Let's test that:

(fileno *s*) returns 19 indeed! Now all I have to do is (fcntl *s*
F_SETFD FD_CLOEXEC) after creating *s*.

So you can close that ticket.

>
> Thanks,
> Ludo’.

Regards.

-- 

Bernard




Reply sent to Ludovic Courtès <ludo <at> gnu.org>:
You have taken responsibility. (Mon, 16 Jun 2025 13:38:08 GMT) Full text and rfc822 format available.

Notification sent to burban <at> opopop.net:
bug acknowledged by developer. (Mon, 16 Jun 2025 13:38:09 GMT) Full text and rfc822 format available.

Message #16 received at 78757-done <at> debbugs.gnu.org (full text, mbox):

From: Ludovic Courtès <ludo <at> gnu.org>
To: burban <at> opopop.net
Cc: 78757-done <at> debbugs.gnu.org
Subject: Re: bug#78757: shepherd: dangling file descriptor to /dev/console
Date: Mon, 16 Jun 2025 15:35:19 +0200
Hi,

burban <at> opopop.net writes:

>> ‘shepherd’ marks all previously-opened FDs as O_CLOEXEC upfront—see
>> ‘mark-as-close-on-exec’ in ‘shepherd.scm’.  Those opened later are
>> opened with O_CLOEXEC, except for user code that explicitly omits the
>> O_CLOEXEC flag.
>
> Hmmm.... I have at one point (before the above (port-for-each ...)
>
> (define *s* (open-output-file "/proc/self/fd/1"))
>
> to have an early log output to (on ordinary PC) /dev/tty1. But maybe /dev/tty1
> is a synonym for /dev/console. Let's test that:
>
> (fileno *s*) returns 19 indeed! Now all I have to do is (fcntl *s*
> F_SETFD FD_CLOEXEC) after creating *s*.

Ah yes, it’s easy to shot oneself in the foot.  ;-)

To reduce the risks, ‘shepherd’ replaces ‘call-with-input-file’ and
‘call-with-output-file’ with O_CLOEXEC variants (commit
47c693d51a991e9a3d5ed6e75760c61e329cc537) because it wouldn’t make much
sense to not have O_CLOEXEC for these.  However, the other procedures
are left unchanged because users might need it.

> So you can close that ticket.

Thanks,
Ludo’.




This bug report was last modified 1 day ago.

Previous Next


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