[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