Bug 1614162

Summary: fix-info-dir hangs when installing to a chroot
Product: [Fedora] Fedora Reporter: Daniel Mach <dmach>
Component: texinfoAssignee: Jason Tibbitts <j>
Status: CLOSED ERRATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 29CC: kasal, kevin, novyjindrich, otaylor, pertusus, pmatilai, vcrhonek
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: texinfo-6.5-11.fc29 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2018-10-08 19:04:29 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Daniel Mach 2018-08-09 06:18:00 UTC
I'm installing RPMs to a installroot and the transaction got stuck on following process:
/bin/sh /usr/sbin/fix-info-dir --create /usr/share/info/dir

Reproducer:
upgrade dnf and libdnf to the latest builds (they may not be available in repos yet)
$ koji download-build --arch=x86_64 --arch=noarch libdnf-0.17.0-1.fc29
$ koji download-build --arch=x86_64 --arch=noarch dnf-3.2.0-1.fc29
$ dnf install ./*.rpm

$ dnf --installroot=/tmp/foo --disablerepo='*' --releasever=29 --nogpgcheck --repofrompath=_rawhide,http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os/ --repofrompath=_rawhide-modular,http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/Modular/x86_64/os/ --setopt='module_platform_id=platform:f29' install @django:1.6/default


Strace shows that the process is looking for quite unexpected files such as "can't"; This is running in an infinite loop.

rt_sigprocmask(SIG_BLOCK, [CHLD], ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], 8) = 0
rt_sigprocmask(SIG_SETMASK, ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], NULL, 8) = 0
faccessat(AT_FDCWD, "can't?", R_OK)     = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "can't?.info", R_OK) = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "can't?.gz", R_OK)  = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "can't?.info.gz", R_OK) = -1 ENOENT (No such file or directory)
fcntl(1, F_GETFD)                       = 0
fcntl(1, F_DUPFD, 10)                   = 12
fcntl(1, F_GETFD)                       = 0
fcntl(12, F_SETFD, FD_CLOEXEC)          = 0
dup2(2, 1)                              = 1
fcntl(2, F_GETFD)                       = 0
write(1, "/usr/sbin/fix-info-dir:226: can't find info file for can't??\n", 61) = 61
dup2(12, 1)                             = 1
fcntl(12, F_GETFD)                      = 0x1 (flags FD_CLOEXEC)
close(12)                               = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], 8) = 0
rt_sigprocmask(SIG_SETMASK, ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], NULL, 8) = 0
ioctl(0, TCGETS, 0x7ffd7eb8e830)        = -1 ENOTTY (Inappropriate ioctl for device)
lseek(0, 0, SEEK_CUR)                   = 45006242
read(0, "/usr/sbin/fix-info-dir:226: can't find info file for find?\n/usr/sbin/fix-info-dir:226: can't find info file for info?\n/usr/sbin/", 128) = 128
lseek(0, -69, SEEK_CUR)                 = 45006301
rt_sigprocmask(SIG_BLOCK, [CHLD], ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], 8) = 0
rt_sigprocmask(SIG_SETMASK, ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], NULL, 8) = 0
openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=260, ...}) = 0
getdents64(3, /* 13 entries */, 32768)  = 440
getdents64(3, /* 0 entries */, 32768)   = 0
close(3)                                = 0
faccessat(AT_FDCWD, "/usr/sbin/fix-info-dir:226:", R_OK) = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "/usr/sbin/fix-info-dir:226:.info", R_OK) = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "/usr/sbin/fix-info-dir:226:.gz", R_OK) = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "/usr/sbin/fix-info-dir:226:.info.gz", R_OK) = -1 ENOENT (No such file or directory)
fcntl(1, F_GETFD)                       = 0
fcntl(1, F_DUPFD, 10)                   = 12
fcntl(1, F_GETFD)                       = 0
fcntl(12, F_SETFD, FD_CLOEXEC)          = 0
dup2(2, 1)                              = 1
fcntl(2, F_GETFD)                       = 0
write(1, "/usr/sbin/fix-info-dir:226: can't find info file for /usr/sbin/fix-info-dir:226:?\n", 82) = 82
dup2(12, 1)                             = 1
fcntl(12, F_GETFD)                      = 0x1 (flags FD_CLOEXEC)
close(12)                               = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], 8) = 0
rt_sigprocmask(SIG_SETMASK, ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], NULL, 8) = 0
faccessat(AT_FDCWD, "can't", R_OK)      = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "can't.info", R_OK) = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "can't.gz", R_OK)   = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "can't.info.gz", R_OK) = -1 ENOENT (No such file or directory)
fcntl(1, F_GETFD)                       = 0
fcntl(1, F_DUPFD, 10)                   = 12
fcntl(1, F_GETFD)                       = 0
fcntl(12, F_SETFD, FD_CLOEXEC)          = 0
dup2(2, 1)                              = 1
fcntl(2, F_GETFD)                       = 0
write(1, "/usr/sbin/fix-info-dir:226: can't find info file for can't?\n", 60) = 60
dup2(12, 1)                             = 1
fcntl(12, F_GETFD)                      = 0x1 (flags FD_CLOEXEC)
close(12)                               = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], 8) = 0
rt_sigprocmask(SIG_SETMASK, ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], NULL, 8) = 0
faccessat(AT_FDCWD, "find", R_OK)       = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "find.info", R_OK)  = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "find.gz", R_OK)    = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "find.info.gz", R_OK) = -1 ENOENT (No such file or directory)
fcntl(1, F_GETFD)                       = 0
fcntl(1, F_DUPFD, 10)                   = 12
fcntl(1, F_GETFD)                       = 0
fcntl(12, F_SETFD, FD_CLOEXEC)          = 0
dup2(2, 1)                              = 1
fcntl(2, F_GETFD)                       = 0
write(1, "/usr/sbin/fix-info-dir:226: can't find info file for find?\n", 59) = 59
dup2(12, 1)                             = 1
fcntl(12, F_GETFD)                      = 0x1 (flags FD_CLOEXEC)
close(12)                               = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], 8) = 0
rt_sigprocmask(SIG_SETMASK, ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], NULL, 8) = 0
faccessat(AT_FDCWD, "info", R_OK)       = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "info.info", R_OK)  = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "info.gz", R_OK)    = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "info.info.gz", R_OK) = -1 ENOENT (No such file or directory)
fcntl(1, F_GETFD)                       = 0
fcntl(1, F_DUPFD, 10)                   = 12
fcntl(1, F_GETFD)                       = 0
fcntl(12, F_SETFD, FD_CLOEXEC)          = 0
dup2(2, 1)                              = 1
fcntl(2, F_GETFD)                       = 0
write(1, "/usr/sbin/fix-info-dir:226: can't find info file for info?\n", 59) = 59
dup2(12, 1)                             = 1
fcntl(12, F_GETFD)                      = 0x1 (flags FD_CLOEXEC)
close(12)                               = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], 8) = 0
rt_sigprocmask(SIG_SETMASK, ~[ILL ABRT BUS FPE KILL SEGV CHLD STOP TSTP RTMIN RT_1], NULL, 8) = 0
faccessat(AT_FDCWD, "file", R_OK)       = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "file.info", R_OK)  = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "file.gz", R_OK)    = -1 ENOENT (No such file or directory)
faccessat(AT_FDCWD, "file.info.gz", R_OK) = -1 ENOENT (No such file or directory)

Comment 1 Jan Kurik 2018-08-14 11:01:32 UTC
This bug appears to have been reported against 'rawhide' during the Fedora 29 development cycle.
Changing version to '29'.

Comment 2 Daniel Mach 2018-08-16 13:29:37 UTC
Not sure if it's related, but I hit another problem with texinfo:
install-info: No such file or directory for /dev/null

The message is probably expected, because there's not /dev mounted in the chroot.

The completely empty chroot might be an important detail to reproduce the originally reported issue.

Comment 3 Owen Taylor 2018-08-20 20:47:06 UTC
Ran into this, and while I couldn't a consistent reproducer, it's pretty clear what is going on:

%transfiletriggerin -n info -- %{_infodir}
[ -f %{_infodir}/dir ] && create_arg="" || create_arg="--create"
%{_sbindir}/fix-info-dir $create_arg %{_infodir}/dir &>/dev/null

And 'fix-info-dir --create %{_infodir}' uses /dev/null as the "skeleton", assuming that it will act like an empty file. So the script is being run output'ing to /dev/null and also reading from /dev/null, and if the stars/buffering align wrong, it's going to read what it's writing and go into an infinite loop.

I think there's two possible responses:
 - Say that someone setting up an install root needs to make sure there's a real /dev/null in it. Many scripts count on output to /dev/null
 - Make the script not to rely on reading from /dev/null

Comment 4 Vitezslav Crhonek 2018-08-21 07:21:05 UTC
(In reply to Owen Taylor from comment #3)
> Ran into this, and while I couldn't a consistent reproducer...

This seems to be reliable reproducer:
# dnf --installroot=/tmp/foo --disablerepo='*' --releasever=29 --nogpgcheck --repofrompath=_rawhide,http://download.fedoraproject.org/pub/fedora/linux/development/rawhide/Everything/x86_64/os/ install mrtg

And then it can be reproduced again (after you kill the first infinite loop) if you chroot into /tmp/foo then and re-run the script:
# /bin/sh /usr/sbin/fix-info-dir --create /usr/share/info/dir

Comment 5 Kevin Fenzi 2018-10-04 17:46:12 UTC
We are hitting this in composes now too... oddly only on armv7 / s390x builders, so I suspect there might be some race also?

It seems to be because the script reads from /dev/null, and the transfiletriggerin redirects its output to /dev/null, so it gets in a loop when /dev/null doesn't exist.

Comment 6 Jason Tibbitts 2018-10-04 20:18:09 UTC
Been looking at the same problem breaking the rawhide appliance composes; they don't have a /dev set up so the thing ends up looping in exactly the same way.  Note that it only loops if you redirect stderr to /dev/null.

While it's certainly reasonable to say that a proper /dev should be set up before running any RPM scriptlets, it takes all of two lines to make the script not expect to read from /dev/null.  In order to make life easier for the releng folks who have been beating on this, I'm going to go ahead and push a patch to rawhide.  I hope that doesn't upset anyone; if it does, I'll do the work to revert if it does.  I have run this in the chroot above and verified that it both fails to infloop where the original would, and produces the same/correct output.

--- a/contrib/fix-info-dir
+++ b/contrib/fix-info-dir
@@ -123,6 +123,7 @@ if test "$CREATE_NODE"; then
                fi
                shift
        else
+               SKIP_READ=yes
                SKELETON=/dev/null

        fi
@@ -187,7 +188,7 @@ DIR_FILE_END_OF_FILE

        # Read one line from the file.  This is so that we can echo lines with
        # whitespace and quoted characters in them.
-       while read fileline; do
+       while test -z "$SKIP_READ" && read fileline; do
                # flag fancy features
                if test ! -z "$echoline"; then        # echo line
                        echo "$fileline"

Comment 7 Kevin Fenzi 2018-10-08 01:50:41 UTC
Can we get a f29 update as well? This is hitting f29 composes also now...

Comment 8 Fedora Update System 2018-10-08 02:58:00 UTC
texinfo-6.5-11.fc29 has been submitted as an update to Fedora 29. https://bodhi.fedoraproject.org/updates/FEDORA-2018-d3e4a6577d

Comment 9 Fedora Update System 2018-10-08 14:55:47 UTC
texinfo-6.5-11.fc29 has been pushed to the Fedora 29 testing repository. If problems still persist, please make note of it in this bug report.
See https://fedoraproject.org/wiki/QA:Updates_Testing for
instructions on how to install test updates.
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2018-d3e4a6577d

Comment 10 Fedora Update System 2018-10-08 19:04:29 UTC
texinfo-6.5-11.fc29 has been pushed to the Fedora 29 stable repository. If problems still persist, please make note of it in this bug report.