[File] [PATCH] save/restore full sigaction for SIGPIPE, and only when needed
Denys Vlasenko
dvlasenk at redhat.com
Mon May 6 08:30:11 UTC 2019
file_zmagic() decompresses potentially compressed examined file.
Since uncompressing tool can fail and writing to closed pipe
sends SIGPIPE, there is code to disable SIGPIPE.
It has one problem:
call to signal() does not save struct sigaction (saves only
signal handler address), so the restored signal handling can
be incorrect - e.g. SA_RESTART bit can be different.
And two missed optimizations:
= The saving/restoring of SIGPIPE is done even if file turns out
to be *not* compressed, and no decompressor is called.
= If old signal was already SIG_IGN, no need to restore it.
This causes, for example, ~160000 unnecessary calls
to rt_sigaction() when rpmbuild generates kernel rpms.
Signed-off-by: Denys Vlasenko <dvlasenk at redhat.com>
---
src/compress.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/src/compress.c b/src/compress.c
index 1e85ae93..cd67edaa 100644
--- a/src/compress.c
+++ b/src/compress.c
@@ -226,12 +226,12 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name)
int fd = b->fd;
const unsigned char *buf = CAST(const unsigned char *, b->fbuf);
size_t nbytes = b->flen;
- sig_t osigpipe;
+ int sa_saved = 0;
+ struct sigaction sig_act;
if ((ms->flags & MAGIC_COMPRESS) == 0)
return 0;
- osigpipe = signal(SIGPIPE, SIG_IGN);
for (i = 0; i < ncompr; i++) {
int zm;
if (nbytes < compr[i].maglen)
@@ -246,6 +246,21 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name)
if (!zm)
continue;
+
+ /* Prevent SIGPIPE death if child dies unexpectedly */
+ if (!sa_saved) {
+ //We can use sig_act for both new and old, but
+ // sigaction(SIGPIPE, &sig_act, &sig_act);
+ //results in bogus gcc warning:
+ //"warning: passing argument 3 to restrict-qualified parameter aliases with argument 2"
+ //oh well...
+ struct sigaction new_act;
+ memset(&new_act, 0, sizeof(new_act));
+ new_act.sa_handler = SIG_IGN;
+ (void)sigaction(SIGPIPE, &new_act, &sig_act);
+ sa_saved = 1;
+ }
+
nsz = nbytes;
urv = uncompressbuf(fd, ms->bytes_max, i, buf, &newbuf, &nsz);
DPRINTF("uncompressbuf = %d, %s, %" SIZE_T_FORMAT "u\n", urv,
@@ -302,7 +317,9 @@ file_zmagic(struct magic_set *ms, const struct buffer *b, const char *name)
out:
DPRINTF("rv = %d\n", rv);
- (void)signal(SIGPIPE, osigpipe);
+ if (sa_saved && sig_act.sa_handler != SIG_IGN)
+ (void)sigaction(SIGPIPE, &sig_act, NULL);
+
free(newbuf);
ms->flags |= MAGIC_COMPRESS;
DPRINTF("Zmagic returns %d\n", rv);
--
2.21.0
More information about the File
mailing list