On Wednesday 28 January 2009 16:03, Ursus wrote:
> In the uclibc sources I found that uclibc calls kernel ppoll with four
> arguments:
> _syscall4(int, __libc_ppoll, struct pollfd *, fds,
> nfds_t, nfds, const struct timespec *, timeout,
> const __sigset_t *, sigmask)
>
> But the kernel ppoll (sys_ppoll) declaration specifies five parameters:
> long sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
> struct timespec __user *tsp, const sigset_t __user *sigmask,
> size_t sigsetsize)
>
>
> I substituted the ordinary ppoll call with indirect call to see if above
> is true.
> syscall(SYS_ppoll, fds, count, &timeout, &sigmask, sizeof(sigset_t));
> Strace returned:
> ...
> ppoll([{fd=0, events=POLLIN}], 1, {5, 0}, [], 128) = -1 EINVAL (Invalid
> argument)
> ...
>
> I made a little research and figured out that the kernel expects last
> argument to be 16 (128 / 8).
I believe you are wrong here. All arches except MIPS have 64 signals
and therefore need 64-bit sigset_t. 64 bits == 8 bytes, not 16.
The rest of your analysis is correct.
> That confused me because I thought the
> sizeof(sigset_t) returns the same in kernel and user space.
Yes, it wasn't, we had glibc-like overblown 1024-bit sigset_t.
(That's where 128 came from in your code. 1024/8 = 128)
It will match kernel's sigset_t starting from 0.9.31.
Please try attached patch.
--
vda
diff -d -urpN uClibc.0/libc/sysdeps/linux/common/ppoll.c uClibc.1/libc/sysdeps/linux/common/ppoll.c
--- uClibc.0/libc/sysdeps/linux/common/ppoll.c 2009-01-08 03:47:48.000000000 +0100
+++ uClibc.1/libc/sysdeps/linux/common/ppoll.c 2009-01-29 00:34:19.000000000 +0100
@@ -17,6 +17,7 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
+#include <signal.h>
#include <sys/syscall.h>
#include <sys/poll.h>
@@ -26,24 +27,26 @@
# define __NR___libc_ppoll __NR_ppoll
static __always_inline
-_syscall4(int, __libc_ppoll, struct pollfd *, fds,
- nfds_t, nfds, const struct timespec *, timeout,
- const __sigset_t *, sigmask)
+_syscall5(int, __libc_ppoll,
+ struct pollfd *, fds,
+ nfds_t, nfds,
+ const struct timespec *, timeout,
+ const __sigset_t *, sigmask,
+ size_t, sigsetsize)
int
-ppoll (struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
+ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
const __sigset_t *sigmask)
{
- /* The Linux kernel can in some situations update the timeout value.
- We do not want that so use a local variable. */
- struct timespec tval;
- if (timeout != NULL)
- {
- tval = *timeout;
- timeout = &tval;
- }
+ /* The Linux kernel can in some situations update the timeout value.
+ We do not want that so use a local variable. */
+ struct timespec tval;
+ if (timeout != NULL) {
+ tval = *timeout;
+ timeout = &tval;
+ }
- return __libc_ppoll(fds, nfds, timeout, sigmask);
+ return __libc_ppoll(fds, nfds, timeout, sigmask, _NSIG / 8);
}
libc_hidden_def(ppoll)
_______________________________________________
uClibc mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/uclibc