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

Reply via email to