chiark / gitweb /
klibc: version 1.0.14
[elogind.git] / klibc / klibc / sigaction.c
index 819ffd4fe82efbc812d14d300fcdb95b2b4d54a5..85f42a244cc65ff7d65f6bde9a21a8c1e146aadb 100644 (file)
@@ -5,11 +5,40 @@
 #include <signal.h>
 #include <sys/syscall.h>
 
-#ifndef __NR_sigaction
+__extern void __sigreturn(void);
+__extern int __sigaction(int, const struct sigaction *, struct sigaction *);
+__extern int __rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t);
 
 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact)
 {
-  return rt_sigaction(sig, act, oact, sizeof(sigset_t));
-}
+  int rv;
+
+#if defined(__i386__) || defined(__x86_64__)
+  /* x86-64, and the Fedora i386 kernel, are broken without SA_RESTORER */
+  struct sigaction sa;
+
+  if ( act && !(act->sa_flags & SA_RESTORER) ) {
+    sa = *act;
+    act = &sa;
+
+    /* The kernel can't be trusted to have a valid default restorer */
+    sa.sa_flags |= SA_RESTORER;
+    sa.sa_restorer = &__sigreturn;
+  }
+#endif
 
+#ifdef __NR_sigaction
+  rv = __sigaction(sig, act, oact);
+#else
+  rv = __rt_sigaction(sig, act, oact, sizeof(sigset_t));
 #endif
+
+
+#if defined(__i386__) || defined(__x86_64__)
+  if ( oact && (oact->sa_restorer == &__sigreturn) ) {
+    oact->sa_flags &= ~SA_RESTORER;
+  }
+#endif
+
+  return rv;
+}