prevent psignal/psiginfo from clobbering stderr orientation, errno
authorRich Felker <dalias@aerifal.cx>
Thu, 30 Aug 2018 04:00:22 +0000 (00:00 -0400)
committerRich Felker <dalias@aerifal.cx>
Thu, 30 Aug 2018 04:05:52 +0000 (00:05 -0400)
these functions are specified to write to stderr but not set its
orientation, presumably so that they can be used in programs operating
stderr in wide mode. also, they are not allowed to clobber errno on
success. save and restore to meet the requirement.

psiginfo is reduced to a think wrapper around psignal, since it
already behaved the same. if we want to add more detailed siginfo
printing at some point this will need refactoring.

src/signal/psiginfo.c
src/signal/psignal.c

index 57be34cd017ca4041f7cb2029e825ad45e796cd7..2b15982be488dfe4a5b89026edff237fbcb4e13f 100644 (file)
@@ -1,10 +1,6 @@
-#include <stdio.h>
-#include <string.h>
 #include <signal.h>
 
 void psiginfo(const siginfo_t *si, const char *msg)
 {
-       char *s = strsignal(si->si_signo);
-       if (msg) fprintf(stderr, "%s: %s\n", msg, s);
-       else fprintf(stderr, "%s\n", s);
+       psignal(si->si_signo, msg);
 }
index 02f1c7609603885e291d63dcc1f649377b0aa6fb..138dbe00fa07825936a4a59676ea89a8b3c673b4 100644 (file)
@@ -1,10 +1,27 @@
-#include <stdio.h>
+#include "stdio_impl.h"
 #include <string.h>
 #include <signal.h>
+#include <errno.h>
 
 void psignal(int sig, const char *msg)
 {
+       FILE *f = stderr;
        char *s = strsignal(sig);
-       if (msg) fprintf(stderr, "%s: %s\n", msg, s);
-       else fprintf(stderr, "%s\n", s);
+
+       FLOCK(f);
+
+       /* Save stderr's orientation and encoding rule, since psignal is not
+        * permitted to change them. Save errno and restore it if there is no
+        * error since fprintf might change it even on success but psignal is
+        * not permitted to do so. */
+       void *old_locale = f->locale;
+       int old_mode = f->mode;
+       int old_errno = errno;
+
+       if (fprintf(f, "%s%s%s\n", msg?msg:"", msg?": ":"", s)>=0)
+               errno = old_errno;
+       f->mode = old_mode;
+       f->locale = old_locale;
+
+       FUNLOCK(f);
 }