Centralize the log failure printing to a helper function, handle
the common conditions there. Remember the last error and only
print a new one if the error differs to avoid unnecessary flooding.
Finally, make the actual message more concise and mark it for i18n.
Oh and add a testcase as well.
This will still try to perror() in vain even if it's stderr that's
returning the errors in the first place, but maybe that's perror()'s
problem and not ours.
Commit 90d8cc1648 changed SIGPIPE to
be ignored during scriptlet execution - nothing wrong with that, at
that time. However since commit c5f82d3f62
we're *blocking* most signals, and contrary to what glibc manual states [*]
ignored signals are in no way special: they get queued up in the pending
set just like everything else. When unblocked, they are handled by
the signal handler active at the time of unblocking. Which means that
ignoring and then restoring handlers for scriptlets does absolutely
nothing at all in practise.
So instead, make SIGPIPE ignored for the duration of the whole
transaction on rpmsq side, and only restore the old handler
after unblocking the signals at end of transaction.
This doesn't magically make things 100% correct either, ultimately
we should probably handle signals instead of blocking during the main
transaction: we should filter out ANYTHING originating from scriptlets,
something else might make sense to queue up. Or not... Anyway, this'll
have to do for now.
[*] Quoting from https://www.gnu.org/software/libc/manual/html_node/Delivery-of-Signal.html#Delivery-of-Signal as of today:
If the specified action for a kind of signal is to ignore it, then any
such signal which is generated is discarded immediately. This happens
even if the signal is also blocked at the time. A signal discarded in
this way will never be delivered, not even if the program subsequently
specifies a different action for that kind of signal and then unblocks it.
This clearly is NOT the case, at least in the case of Linux kernel which
explicitly notes this specific case since 2003'ish (from kernel/signal.c):
/*
* Blocked signals are never ignored, since the
* signal handler may change by the time it is
* unblocked.
*/
Test for SIGPIPE behavior in three different cases:
- build scriptlets ought to have SIGPIPE working as usual (RhBug:651463)
- SIGPIPE received from install scriptlet (RhBug:1264198) which currently
fails because we end up exiting on that signal after the transaction.
The original case involves file triggers, we simulate it by kill'ing
for simplicitys sake.
- query involving --pipe (RhBug:444389)
Should test for RhBug:471591 too but need a simpler reproducer than
in the bug, leaving that to some rainy day.