[git commit nptl] add non realtime sigwait from master and cleanup a bit

Austin Foxley austinf at cetoncorp.com
Sat Sep 19 02:00:48 UTC 2009


commit: http://git.uclibc.org/uClibc/commit/?id=6a425eea7816aa21cfbef8bed33fde10b7a44bdf
branch: http://git.uclibc.org/uClibc/commit/?id=refs/heads/nptl

Signed-off-by: Austin Foxley <austinf at cetoncorp.com>
---
 libc/signal/sigwait.c |   79 ++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/libc/signal/sigwait.c b/libc/signal/sigwait.c
index f152088..a47c37c 100644
--- a/libc/signal/sigwait.c
+++ b/libc/signal/sigwait.c
@@ -23,8 +23,6 @@
 #include <signal.h>
 #include <string.h>
 
-libc_hidden_proto(sigwaitinfo)
-
 #ifdef __UCLIBC_HAS_THREADS_NATIVE__
 # include <sysdep-cancel.h>
 
@@ -57,7 +55,6 @@ static int do_sigwait(const sigset_t *set, int *sig)
 
 	/* XXX The size argument hopefully will have to be changed to the
 	   real size of the user-level sigset_t.  */
-#  ifdef INTERNAL_SYSCALL
 	INTERNAL_SYSCALL_DECL(err);
 	do
 		ret = INTERNAL_SYSCALL (rt_sigtimedwait, err, 4, set, NULL,
@@ -71,9 +68,6 @@ static int do_sigwait(const sigset_t *set, int *sig)
 	}
 else
 	ret = INTERNAL_SYSCALL_ERRNO (ret, err);
-#  else
-#   error INTERNAL_SYSCALL must be defined!!!
-#  endif
 
 	return ret;
 }
@@ -92,11 +86,13 @@ int __sigwait (const sigset_t *set, int *sig)
 
 	return result;
 }
-# else
+# else /* __NR_rt_sigtimedwait */
 #  error We must have rt_sigtimedwait defined!!!
 # endif
-#else
-# undef sigwait
+#else /* __UCLIBC_HAS_THREADS_NATIVE__ */
+
+# if define __UCLIBC_HAS_REALTIME__
+
 int __sigwait (const sigset_t *set, int *sig) attribute_hidden;
 int __sigwait (const sigset_t *set, int *sig)
 {
@@ -107,7 +103,68 @@ int __sigwait (const sigset_t *set, int *sig)
 	}
 	return 1;
 }
-#endif
-libc_hidden_proto(sigwait)
+
+# else /* __UCLIBC_HAS_REALTIME__ */
+/* variant without REALTIME extensions */
+
+static smallint was_sig; /* obviously not thread-safe */
+
+static void ignore_signal(int sig)
+{
+	was_sig = sig;
+}
+
+int sigwait (const sigset_t *set, int *sig)
+{
+  sigset_t tmp_mask;
+  struct sigaction saved[NSIG];
+  struct sigaction action;
+  int save_errno;
+  int this;
+
+  /* Prepare set.  */
+  __sigfillset (&tmp_mask);
+
+  /* Unblock all signals in the SET and register our nice handler.  */
+  action.sa_handler = ignore_signal;
+  action.sa_flags = 0;
+  __sigfillset (&action.sa_mask);       /* Block all signals for handler.  */
+
+  /* Make sure we recognize error conditions by setting WAS_SIG to a
+     value which does not describe a legal signal number.  */
+  was_sig = -1;
+
+  for (this = 1; this < NSIG; ++this)
+    if (__sigismember (set, this))
+      {
+        /* Unblock this signal.  */
+        __sigdelset (&tmp_mask, this);
+
+        /* Register temporary action handler.  */
+        /* In Linux (as of 2.6.25), fails only if sig is SIGKILL or SIGSTOP */
+        /* (so, will it work correctly if set has, say, SIGSTOP?) */
+        if (sigaction (this, &action, &saved[this]) != 0)
+          goto restore_handler;
+      }
+
+  /* Now we can wait for signals.  */
+  sigsuspend (&tmp_mask);
+
+ restore_handler:
+  save_errno = errno;
+
+  while (--this >= 1)
+    if (__sigismember (set, this))
+      /* We ignore errors here since we must restore all handlers.  */
+      sigaction (this, &saved[this], NULL);
+
+  __set_errno (save_errno);
+
+  /* Store the result and return.  */
+  *sig = was_sig;
+  return was_sig == -1 ? -1 : 0;
+}
+# endif /* __UCLIBC_HAS_REALTIME__ */
+#endif /* __UCLIBC_HAS_THREADS_NATIVE__ */
 weak_alias(__sigwait,sigwait)
 libc_hidden_def(sigwait)
-- 
1.6.3.3



More information about the uClibc-cvs mailing list