[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