Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 482758 - sys-process/vixie-cron - makewhatis complains about broken pipes (under systemd)
Summary: sys-process/vixie-cron - makewhatis complains about broken pipes (under systemd)
Status: RESOLVED FIXED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: [OLD] Core system (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: Cron Team
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-08-28 06:24 UTC by redneb
Modified: 2015-04-24 20:30 UTC (History)
5 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description redneb 2013-08-28 06:24:55 UTC
Ever since I switched my system to systemd, makewhatis (which is ran by default by a daily cron job) gives several errors like the following:

bzcat: I/O or other error, bailing out.  Possible reason follows.
bzcat: Broken pipe
        Input file = /usr/share/man/man1/./curl.1.bz2, output file = (stdout)

This only happens the first time makewhatis is ran after a package was installed (curl in this case). If I remove the -u switch from /etc/cron.daily/makewhatis then it happens every time (that's because the removal of this switch forces makewhatis to scan all man pages, not just the new ones). This does not happen when I manually execute makewhatis myself and it does not happen when makewhatis is executed by vixie-cron when run under openrc. Thus I conclude that it has to do with systemd.
Comment 1 redneb 2013-08-28 06:29:48 UTC
Forgot to mention that I also get the errors when I run makewhatis using a systemd unit file like this:

[Service]
ExecStart=/usr/sbin/makewhatis

that is, bypassing vixie-cron completely. This makes me rule out the possibility that it is vixie-cron's fault.
Comment 2 redneb 2013-08-28 07:24:18 UTC
Ok, I found the culprit, it's systemd as I suspected. What happens is that makewhatis calls bzcat in order to uncompress the compressed man pages and after it reads the first few lines it closes the pipe. Under systemd, this causes the bzcat process to receive a SIGPIPE signal and its handler then produces the above error message. When makewhatis is ran directly in a terminal or under openrc this does not happen.
Comment 3 redneb 2013-08-28 07:37:58 UTC
Ok, so systemd offers an option for the [Service] section called IgnoreSIGPIPE. Setting it to "no" (the default is yes) in the vixie-cron unit file fixes the issue.

What's the best solution here?
Comment 4 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2013-08-28 15:35:20 UTC
Do I understand correctly that you are concerned of it happening when vixie-cron is spawned by systemd, correct?
Comment 5 redneb 2013-08-28 18:50:01 UTC
(In reply to Michał Górny from comment #4)
> Do I understand correctly that you are concerned of it happening when
> vixie-cron is spawned by systemd, correct?

Yes. It is a systemd bug, not a sys-apps/man bug.
Comment 6 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2013-08-28 19:01:07 UTC
If it's a bug, then what is the fix?
Comment 7 Mike Gilbert gentoo-dev 2013-08-28 19:06:23 UTC
Maybe sysvinit or start-stop-daemon calls signal(SIGPIPE, SIG_IGN) at some point, and this gets inherited by cron?
Comment 8 redneb 2013-08-28 19:17:36 UTC
Here's a more technical explanation of what happens: makewhatis scans all files in /usr/share/man/ and it reads the first few lines from each of them. Because they are compressed, it uses (bz|z|xz)cat to do that. Sort of like this:

bzcat /usr/share/man/man1/emerge.1.bz2 | head

Now if you run the above command in a terminal, it will not produce any error/warning. But if you run the following:

perl -e '$SIG{PIPE}="IGNORE"; system "bzcat /usr/share/man/man1/emerge.1.bz2 | head"'

you will get the following error:

bzcat: I/O or other error, bailing out.  Possible reason follows.
bzcat: Broken pipe
	Input file = /usr/share/man/man1/emerge.1.bz2, output file = (stdout)

That's exactly what happens with systemd; it ignores SIGPIPE by default [1]. So when systemd executes vixie-cron then vixie-cron inherits this behavior. Then vixie-cron in turn executes makewhatit which executes bzcat.

[1] http://cgit.freedesktop.org/systemd/systemd/commit/?id=353e12c2f4a9e96a47eb80b80d2ffb7bc1d44a1b
Comment 9 redneb 2013-08-28 19:43:27 UTC
(In reply to Mike Gilbert from comment #7)
> Maybe sysvinit or start-stop-daemon calls signal(SIGPIPE, SIG_IGN) at some
> point, and this gets inherited by cron?

Oops, I didn't see that comment before I posted my previous comment. Yes, someone does call signal(SIGPIPE, SIG_IGN) and that someone is systemd. It seems that bzcat behaves in the opposite way I would naively expect: If SIGPIPE is being ignored by its caller then it complains. If the signal handler of SIGPIPE is set to SIG_DFL then it does not complain at all. You can verify that by trying the following two commands:

perl -e '$SIG{PIPE}="IGNORE"; system "bzcat /usr/share/man/man1/emerge.1.bz2 | head"'

perl -e '$SIG{PIPE}="DEFAULT"; system "bzcat /usr/share/man/man1/emerge.1.bz2 | head"'
Comment 10 Mike Gilbert gentoo-dev 2013-08-28 21:23:49 UTC
(In reply to redneb from comment #9)

Ah, I had it reversed. Yeah, you have it nailed.

So, either vixie-cron needs to reset the SIGPIPE handler to SIG_DFL, or we should update the unit to set IgnoreSIGPIPE=no.
Comment 11 Mike Gilbert gentoo-dev 2013-08-28 21:29:47 UTC
FWIW, Fedora's fork of vixie-cron (sys-process/cronie) resets SIGPIPE for child processes.

https://git.fedorahosted.org/cgit/cronie.git/commit/?id=ee4cbe7659ede3f61db18cc922ee0e27268a8579
Comment 12 Mike Gilbert gentoo-dev 2013-08-28 21:32:07 UTC
Reassigning to vixie-cron maintainers.
Comment 13 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2013-08-28 21:38:15 UTC
But shouldn't makewhatis be ready to run with whatever signal handlers are installed on its parent? IMO if it relies on given behavior, it should set signal handlers itself.
Comment 14 Mike Gilbert gentoo-dev 2013-08-28 21:53:41 UTC
(In reply to Michał Górny from comment #13)

Hmm... I suppose it technically should.

However, since cron daemons invoke random shell commands which often involve pipelines, it seems like it a more sensible default would be a good idea.
Comment 15 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2013-08-28 22:07:15 UTC
Sure but I think we should fix it in all the places.
Comment 16 Mike Gilbert gentoo-dev 2013-08-28 22:33:24 UTC
I did some digging. makewhatis is a shell script, so I think the only way it can set signal handlers is using the trap built-in.

POSIX says this:

http://pubs.opengroup.org/onlinepubs/009695399/utilities/trap.html

"Signals that were ignored on entry to a non-interactive shell cannot be trapped or reset, although no error need be reported when attempting to do so."


So, to reset the SIGPIPE handler, makewhatis would need to be rewritten in a more complete programming language, or it would have to invoke some helper utility to reset the signal and start the pipelined processes.
Comment 17 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2013-08-29 06:32:41 UTC
Hmm, so everything that spawns shell should reset ignored signals to defaults for consistency, correct?
Comment 18 Mike Gilbert gentoo-dev 2013-08-29 14:30:52 UTC
Yeah, that seems to be the case.
Comment 19 SpanKY gentoo-dev 2013-09-12 21:31:17 UTC
(In reply to Mike Gilbert from comment #16)

that's the old POSIX spec.  here's the new link:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#trap

you should update your bookmarks accordingly as there's lots of goodies in the newer one (not that it matters for this specific bug).
Comment 20 Mike Gilbert gentoo-dev 2015-04-24 20:30:20 UTC
+  24 Apr 2015; Mike Gilbert <floppym@gentoo.org> files/vixie-cron.service:
+  Set IgnoreSIGPIPE=false, bug 482758.

I'm not sure this is worth a revbump.