GNU bug report logs -
#78757
shepherd: dangling file descriptor to /dev/console
Previous Next
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.
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):
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):
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):
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):
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.