ソースを参照

libc: Fix cancellation handling in some C functions

According to POSIX.1-2008 standard, the following syscalls shall be
cancellation points : waitid, sleep, fdatasync, ppoll.
Further, if generic syscall is not available and stubs are
configured, provide the stub implementation for function.

Signed-off-by: Salvatore Cro <salvatore.cro@st.com>
Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
Salvatore Cro 14 年 前
コミット
4b88e6e858

+ 1 - 1
libc/sysdeps/linux/common/Makefile.in

@@ -27,7 +27,7 @@ endif
 ifneq ($(UCLIBC_LINUX_SPECIFIC),y)
 ifneq ($(UCLIBC_LINUX_SPECIFIC),y)
 # we need these internally: fstatfs.c statfs.c
 # we need these internally: fstatfs.c statfs.c
 CSRC := $(filter-out capget.c capset.c inotify.c ioperm.c iopl.c madvise.c \
 CSRC := $(filter-out capget.c capset.c inotify.c ioperm.c iopl.c madvise.c \
-	modify_ldt.c personality.c prctl.c readahead.c reboot.c \
+	modify_ldt.c personality.c ppoll.c prctl.c readahead.c reboot.c \
 	remap_file_pages.c sched_getaffinity.c sched_setaffinity.c \
 	remap_file_pages.c sched_getaffinity.c sched_setaffinity.c \
 	sendfile64.c sendfile.c setfsgid.c setfsuid.c setresuid.c \
 	sendfile64.c sendfile.c setfsgid.c setfsuid.c setresuid.c \
 	splice.c vmsplice.c tee.c signalfd.c swapoff.c swapon.c \
 	splice.c vmsplice.c tee.c signalfd.c swapoff.c swapon.c \

+ 34 - 1
libc/sysdeps/linux/common/fdatasync.c

@@ -14,4 +14,37 @@
 # define __NR_fdatasync __NR_osf_fdatasync
 # define __NR_fdatasync __NR_osf_fdatasync
 #endif
 #endif
 
 
-_syscall1(int, fdatasync, int, fd)
+#ifdef __NR_fdatasync
+
+# ifdef __UCLIBC_HAS_THREADS_NATIVE__
+# include <sysdep-cancel.h>
+# else
+# define SINGLE_THREAD_P 1
+# endif
+
+#define __NR___syscall_fdatasync __NR_fdatasync
+
+static __always_inline
+_syscall1(int, __syscall_fdatasync, int, fd)
+
+int fdatasync(int fd)
+{
+	if (SINGLE_THREAD_P)
+		return __syscall_fdatasync(fd);
+
+# ifdef __UCLIBC_HAS_THREADS_NATIVE__
+	int oldtype = LIBC_CANCEL_ASYNC ();
+	int result = __syscall_fdatasync(fd);
+	LIBC_CANCEL_RESET (oldtype);
+	return result;
+# endif
+}
+
+#elif defined __UCLIBC_HAS_STUBS__
+/* no syscall available, so provide a stub */
+int fdatasync(int fd)
+{
+	__set_errno(ENOSYS);
+	return -1;
+}
+#endif

+ 14 - 1
libc/sysdeps/linux/common/ppoll.c

@@ -24,6 +24,12 @@
 #include <stddef.h>
 #include <stddef.h>
 
 
 #if defined __NR_ppoll && defined __UCLIBC_LINUX_SPECIFIC__
 #if defined __NR_ppoll && defined __UCLIBC_LINUX_SPECIFIC__
+# ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#  include <sysdep-cancel.h>
+# else
+#  define SINGLE_THREAD_P 1
+# endif
+
 int
 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)
        const sigset_t *sigmask)
@@ -35,8 +41,15 @@ ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout,
 		tval = *timeout;
 		tval = *timeout;
 		timeout = &tval;
 		timeout = &tval;
 	}
 	}
+  if (SINGLE_THREAD_P)
+		return INLINE_SYSCALL(ppoll, 5, fds, nfds, timeout, sigmask, _NSIG / 8);
 
 
-	return INLINE_SYSCALL(ppoll, 5, fds, nfds, timeout, sigmask, _NSIG / 8);
+# ifdef __UCLIBC_HAS_THREADS_NATIVE__
+	int oldtype = LIBC_CANCEL_ASYNC ();
+	int result = INLINE_SYSCALL(ppoll, 5, fds, nfds, timeout, sigmask, _NSIG / 8);
+	LIBC_CANCEL_RESET (oldtype);
+	return result;
+# endif
 }
 }
 libc_hidden_def(ppoll)
 libc_hidden_def(ppoll)
 #endif
 #endif

+ 23 - 4
libc/sysdeps/linux/common/waitid.c

@@ -14,20 +14,37 @@
 # include <sys/syscall.h>
 # include <sys/syscall.h>
 
 
 # ifdef __NR_waitid
 # ifdef __NR_waitid
+
+#  ifdef __UCLIBC_HAS_THREADS_NATIVE__
+#  include <sysdep-cancel.h>
+#  else
+#  define SINGLE_THREAD_P 1
+#  endif
+
 /* The waitid() POSIX interface takes 4 arguments, but the kernel function
 /* The waitid() POSIX interface takes 4 arguments, but the kernel function
  * actually takes 5.  The fifth is a pointer to struct rusage.  Make sure
  * actually takes 5.  The fifth is a pointer to struct rusage.  Make sure
  * we pass NULL rather than letting whatever was in the register bleed up.
  * we pass NULL rather than letting whatever was in the register bleed up.
  */
  */
 #define __NR_waitid5 __NR_waitid
 #define __NR_waitid5 __NR_waitid
-static _syscall5(int, waitid5, idtype_t, idtype, id_t, id, siginfo_t*, infop,
+static __always_inline
+_syscall5(int, waitid5, idtype_t, idtype, id_t, id, siginfo_t*, infop,
                  int, options, struct rusage*, ru)
                  int, options, struct rusage*, ru)
 # endif
 # endif
 
 
 int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options)
 int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options)
 {
 {
 # ifdef __NR_waitid
 # ifdef __NR_waitid
-	return waitid5(idtype, id, infop, options, NULL);
-# else
+ if (SINGLE_THREAD_P)
+		return waitid5(idtype, id, infop, options, NULL);
+
+#  ifdef __UCLIBC_HAS_THREADS_NATIVE__
+	int oldtype = LIBC_CANCEL_ASYNC ();
+	int result = waitid5(idtype, id, infop, options, NULL);
+	LIBC_CANCEL_RESET (oldtype);
+	return result;
+#  endif
+
+# elif defined __NR_waitpid
 	switch (idtype) {
 	switch (idtype) {
 		case P_PID:
 		case P_PID:
 			if (id <= 0)
 			if (id <= 0)
@@ -56,7 +73,9 @@ int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options)
 	if (infop->si_pid < 0)
 	if (infop->si_pid < 0)
 		return infop->si_pid;
 		return infop->si_pid;
 	return 0;
 	return 0;
+# else
+ __set_errno(ENOSYS);
+ return -1;
 # endif
 # endif
 }
 }
-
 #endif
 #endif

+ 6 - 1
libc/unistd/sleep.c

@@ -54,7 +54,12 @@ unsigned int sleep (unsigned int seconds)
 
 
     /* This is not necessary but some buggy programs depend on this.  */
     /* This is not necessary but some buggy programs depend on this.  */
     if (seconds == 0)
     if (seconds == 0)
-	return 0;
+	{
+# ifdef CANCELLATION_P
+		CANCELLATION_P (THREAD_SELF);
+# endif
+		return 0;
+	}
 
 
     /* Linux will wake up the system call, nanosleep, when SIGCHLD
     /* Linux will wake up the system call, nanosleep, when SIGCHLD
        arrives even if SIGCHLD is ignored.  We have to deal with it
        arrives even if SIGCHLD is ignored.  We have to deal with it