|Summary:||rpm leaves duplicate of STDOUT_FILENO in script processes|
|Product:||[Retired] Red Hat Linux||Reporter:||Greg Hudson <ghudson>|
|Component:||rpm||Assignee:||Jeff Johnson <jbj>|
|Status:||CLOSED RAWHIDE||QA Contact:||David Lawrence <dkl>|
|Fixed In Version:||Doc Type:||Bug Fix|
|Doc Text:||Story Points:||---|
|Last Closed:||2001-04-26 12:29:37 UTC||Type:||---|
|oVirt Team:||---||RHEL 7.3 requirements from Atomic Host:|
Description Greg Hudson 2001-04-25 21:42:19 UTC
From Bugzilla Helper: User-Agent: Mozilla/4.76 [en] (X11; U; Linux 2.2.14-12 i686) In runScript() in lib/psm.c (in the current CVS repository; this would be in lib/uninstall.c in rpm 4.0.2), a duplicate of STDOUT_FILENO is created if ts->scriptFd is not set, which is the normal case. (Oddly, there is logic for conditionalizing on rpmIsVerbose() when ts->scriptFd is set, but no such logic otherwise.) The child process does not close "out" when scriptFd is unset, so the script processes run with a duplicate of STDOUT_FILENO in their space. This odd behavior can lead to problems if the script starts a daemon process, even a well-behaved daemon which closes fds 0, 1, and 2. (Some daemons close all fds, but I don't think there is any consensus that a daemon is required to do this.) In that case, the daemon process will still have a reference to rpm's output fd in its file table, so if rpm output was passed through a pipe, the right side of the pipe will never terminate. We don't see this problem in Red Hat RPMs on a modern system because /sbin/initlog (used by "daemon" in initscripts) now closes all file descriptors >= 3 before running the daemon process. This was not always so, and I have encountered hanging pipeline problems upgrading from Red Hat 6.2 or Red Hat 7.0 to Red Hat 7.1 because RPMs like "at" and "gpm", if they happen to be upgraded by the transaction before initscripts is upgraded, will restart their daemons with the daemon process holding the pipe open. The fix is pretty easy. Either stop creating "out" when ts->scriptFd isn't set (and conditionalize the parent's close of "out" on ts->scriptFd being set), or move the child's close of "out" outside of the ts->scriptFd conditional. Reproducible: Sometimes Steps to Reproduce: As noted in the description, producing an actual problem is kind of difficult due to all the players involved like /sbin/initlog. Hopefully my exposition of the bug is sufficient to show its presence.
Comment 1 Jeff Johnson 2001-04-25 22:33:46 UTC
The problem is actually worse than stdout, as the same affected daemons will inherit open rpmdb file descriptors as well. So far, I've been saying Fix the daemon package. as daemons truly must lose all open file descriptors, that's SOP in BSD daemonize() for A Long Time Now. Closing and reopening the rpmdb descriptors, unlike stdout, is trickier ...
Comment 2 Greg Hudson 2001-04-25 23:57:40 UTC
Can't you just set the rpmdb file descriptors FD_CLOEXEC? Unlike stdout, they shouldn't be needed by any subprocess of rpm. Anyway, the overall problem may be larger than stdout, but the stdout problem can have a particularly nasty failure mode, and is easy to fix. Finally, the BSD daemon() function does not close all file descriptors; it merely redirects 0/1/2 to /dev/null. I checked NetBSD, FreeBSD, and OpenBSD; here's a URL to the current NetBSD version for reference. http://cvsweb.netbsd.org/bsdweb.cgi/basesrc/lib/libc/gen/daemon.c?rev=1.8&content-type=text/x-cvsweb-markup
Comment 3 Jeff Johnson 2001-04-26 12:29:32 UTC
Close on exec would work, might have some portability problems. You're correct that stdout is a different, and probably solvable, problem I'll take a look. Thanks for the correction wrto daemonize(), although I'm quite sure that I've seen all file descriptors being routinely closed in BSD code, even though I've mistakenly identified the routine. Let me try a different tack. Any daemon that inherits file descriptors from rpm will inherit file descriptors from whatever program starts the daemon. That indicates that the daemon *must* be fixed, independent of what rpm (or any other program that starts daemons) does. That's the correct way to prevent surprising fd inheiritance.
Comment 4 Jeff Johnson 2002-02-06 22:13:02 UTC
OK, the single open(2) call deep in rpmio now is dressed with FD_CLOEXEC. Will be in rpm-4.0.4-0.30 (and rpm-4.0.4 final). I believe most everything else now sets FD_CLOEXEC, will check. Nothing to be done for stdout/stderr however, they'll inherit from the invoking shell as always.