@@ -398,8 +398,7 @@ tests-reverse += tst-cancel5 tst-cancel23 tst-vfork1x tst-vfork2x
ifeq ($(run-built-tests),yes)
tests-special += $(objpfx)tst-stack3-mem.out $(objpfx)tst-oddstacklimit.out
ifeq ($(build-shared),yes)
-tests-special += $(objpfx)tst-tls6.out $(objpfx)tst-cleanup0-cmp.out \
- $(objpfx)tst-cancel-wrappers.out
+tests-special += $(objpfx)tst-tls6.out $(objpfx)tst-cleanup0-cmp.out
endif
endif
@@ -615,7 +614,7 @@ $(objpfx)$(multidir)/crtn.o: $(objpfx)crtn.o $(objpfx)$(multidir)/
endif
generated += libpthread_nonshared.a \
- multidir.mk tst-atfork2.mtrace tst-cancel-wrappers.out \
+ multidir.mk tst-atfork2.mtrace \
tst-tls6.out
generated += $(objpfx)tst-atfork2.mtrace \
@@ -632,18 +631,6 @@ LDFLAGS-pthread.so += -e __nptl_main
$(objpfx)pt-interp.os: $(common-objpfx)runtime-linker.h
endif
-ifeq ($(run-built-tests),yes)
-ifeq (yes,$(build-shared))
-$(objpfx)tst-cancel-wrappers.out: tst-cancel-wrappers.sh
- $(SHELL) $< '$(NM)' \
- $(common-objpfx)libc_pic.a \
- $(common-objpfx)libc.a \
- $(objpfx)libpthread_pic.a \
- $(objpfx)libpthread.a > $@; \
- $(evaluate-test)
-endif
-endif
-
tst-exec4-ARGS = $(host-test-program-cmd)
$(objpfx)tst-execstack: $(libdl)
deleted file mode 100644
@@ -1,92 +0,0 @@
-#! /bin/sh
-# Test whether all cancelable functions are cancelable.
-# Copyright (C) 2002-2015 Free Software Foundation, Inc.
-# This file is part of the GNU C Library.
-# Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
-
-# The GNU C Library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-
-# The GNU C Library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-
-# You should have received a copy of the GNU Lesser General Public
-# License along with the GNU C Library; if not, see
-# <http://www.gnu.org/licenses/>.
-
-NM="$1"; shift
-while [ $# -gt 0 ]; do
- ( $NM -P $1; echo 'end[end]:' ) | gawk ' BEGIN {
-C["accept"]=1
-C["close"]=1
-C["connect"]=1
-C["creat"]=1
-C["fcntl"]=1
-C["fdatasync"]=1
-C["fsync"]=1
-C["msgrcv"]=1
-C["msgsnd"]=1
-C["msync"]=1
-C["nanosleep"]=1
-C["open"]=1
-C["open64"]=1
-C["pause"]=1
-C["poll"]=1
-C["pread"]=1
-C["pread64"]=1
-C["pselect"]=1
-C["pwrite"]=1
-C["pwrite64"]=1
-C["read"]=1
-C["readv"]=1
-C["recv"]=1
-C["recvfrom"]=1
-C["recvmsg"]=1
-C["select"]=1
-C["send"]=1
-C["sendmsg"]=1
-C["sendto"]=1
-C["sigpause"]=1
-C["sigsuspend"]=1
-C["sigwait"]=1
-C["sigwaitinfo"]=1
-C["tcdrain"]=1
-C["wait"]=1
-C["waitid"]=1
-C["waitpid"]=1
-C["write"]=1
-C["writev"]=1
-C["__xpg_sigpause"]=1
-}
-/:$/ {
- if (seen)
- {
- if (!seen_enable || !seen_disable)
- {
- printf "in '$1'(%s) %s'\''s cancellation missing\n", object, seen
- ret = 1
- }
- }
- seen=""
- seen_enable=""
- seen_disable=""
- object=gensub(/^.*\[(.*)\]:$/, "\\1", 1, $0)
- next
-}
-{
- if (C[$1] && $2 ~ /^[TW]$/)
- seen=$1
- else if ($1 ~ /^([.]|)__(libc|pthread)_enable_asynccancel$/ && $2 == "U")
- seen_enable=1
- else if ($1 ~ /^([.]|)__(libc|pthread)_disable_asynccancel$/ && $2 == "U")
- seen_disable=1
-}
-END {
- exit ret
-}' || exit
- shift
-done
@@ -33,6 +33,10 @@ tf (void *arg)
char buf[100000];
while (write (fd[1], buf, sizeof (buf)) > 0);
+ /* The write can return a value higher than 0 (meaning partial write)
+ due to the SIGCANCEL, but the thread may still be pending
+ cancellation. */
+ pthread_testcancel ();
return (void *) 42l;
}
@@ -49,6 +49,10 @@ sh_body (void)
puts ("read succeeded");
exit (1);
}
+ /* The write can return a value higher than 0 (meaning partial write)
+ due to the SIGCANCEL, but the thread may still be pending
+ cancellation. */
+ pthread_testcancel ();
pthread_cleanup_pop (0);
}
@@ -84,7 +88,8 @@ tf_body (void)
puts ("read succeeded");
exit (1);
}
-
+ /* Check for partial read. */
+ pthread_testcancel ();
read (fd[0], &c, 1);
pthread_cleanup_pop (0);
@@ -50,6 +50,10 @@ sh_body (void)
puts ("read succeeded");
exit (1);
}
+ /* The write can return a value higher than 0 (meaning partial write)
+ due to the SIGCANCEL, but the thread may still be pending
+ cancellation. */
+ pthread_testcancel ();
pthread_cleanup_pop (0);
}
@@ -85,6 +89,8 @@ tf_body (void)
puts ("read succeeded");
exit (1);
}
+ /* Check partial read. */
+ pthread_testcancel ();
read (fd[0], &c, 1);
@@ -38,8 +38,6 @@
#include <sys/un.h>
#include <sys/wait.h>
-#include "pthreadP.h"
-
/* Since STREAMS are not supported in the standard Linux kernel and
there we don't advertise STREAMS as supported is no need to test
@@ -117,7 +115,20 @@ cl (void *arg)
++cl_called;
}
+/* Named pipe used to check for blocking open. It should be closed
+ after the cancellation handling. */
+static char fifoname[] = "/tmp/tst-cancel4-fifo-XXXXXX";
+static int fifofd;
+static void
+cl_fifo (void *arg)
+{
+ ++cl_called;
+
+ unlink (fifoname);
+ close (fifofd);
+ fifofd = -1;
+}
static void *
tf_read (void *arg)
@@ -247,6 +258,10 @@ tf_write (void *arg)
char buf[WRITE_BUFFER_SIZE];
memset (buf, '\0', sizeof (buf));
s = write (fd, buf, sizeof (buf));
+ /* The write can return a value higher than 0 (meaning partial write)
+ due to the SIGCANCEL, but the thread may still be pending
+ cancellation. */
+ pthread_testcancel ();
pthread_cleanup_pop (0);
@@ -781,13 +796,7 @@ tf_sigpause (void *arg)
pthread_cleanup_push (cl, NULL);
-#ifdef SIGCANCEL
- /* Just for fun block the cancellation signal. We need to use
- __xpg_sigpause since otherwise we will get the BSD version. */
- __xpg_sigpause (SIGCANCEL);
-#else
- pause ();
-#endif
+ sigpause (sigmask (SIGINT));
pthread_cleanup_pop (0);
@@ -1143,6 +1152,8 @@ tf_send (void *arg)
char mem[700000];
send (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0);
+ /* Check for partial send. */
+ pthread_testcancel ();
pthread_cleanup_pop (0);
@@ -1396,9 +1407,23 @@ static void *
tf_open (void *arg)
{
if (arg == NULL)
- // XXX If somebody can provide a portable test case in which open()
- // blocks we can enable this test to run in both rounds.
- abort ();
+ {
+ fifofd = mkfifo (fifoname, S_IWUSR | S_IRUSR);
+ if (fifofd == -1)
+ {
+ printf ("%s: mkfifo failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+ else
+ {
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
int r = pthread_barrier_wait (&b2);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
@@ -1407,16 +1432,49 @@ tf_open (void *arg)
exit (1);
}
- r = pthread_barrier_wait (&b2);
+ pthread_cleanup_push (cl_fifo, NULL);
+
+ open (arg ? "Makefile" : fifoname, O_RDONLY);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: open returned\n", __FUNCTION__);
+
+ exit (1);
+}
+
+static void *
+tf_open64 (void *arg)
+{
+ if (arg == NULL)
+ {
+ fifofd = mkfifo (fifoname, S_IWUSR | S_IRUSR);
+ if (fifofd == -1)
+ {
+ printf ("%s: mkfifo failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+ else
+ {
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+ }
+
+ int r = pthread_barrier_wait (&b2);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
{
- printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
exit (1);
}
- pthread_cleanup_push (cl, NULL);
+ pthread_cleanup_push (cl_fifo, NULL);
- open ("Makefile", O_RDONLY);
+ open64 (arg ? "Makefile" : fifoname, O_RDONLY);
pthread_cleanup_pop (0);
@@ -1510,6 +1568,46 @@ tf_pread (void *arg)
exit (1);
}
+static void *
+tf_pread64 (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which pread()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ tempfd = open64 ("Makefile", O_RDONLY);
+ if (tempfd == -1)
+ {
+ printf ("%s: cannot open64 Makefile\n", __FUNCTION__);
+ exit (1);
+ }
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[10];
+ pread64 (tempfd, mem, sizeof (mem), 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: pread64 returned\n", __FUNCTION__);
+
+ exit (1);
+}
static void *
tf_pwrite (void *arg)
@@ -1554,6 +1652,48 @@ tf_pwrite (void *arg)
exit (1);
}
+static void *
+tf_pwrite64 (void *arg)
+{
+ if (arg == NULL)
+ // XXX If somebody can provide a portable test case in which pwrite()
+ // blocks we can enable this test to run in both rounds.
+ abort ();
+
+ char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+ tempfd = mkstemp (fname);
+ if (tempfd == -1)
+ {
+ printf ("%s: mkstemp failed\n", __FUNCTION__);
+ exit (1);
+ }
+ unlink (fname);
+
+ int r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ r = pthread_barrier_wait (&b2);
+ if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+ {
+ printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+ exit (1);
+ }
+
+ pthread_cleanup_push (cl, NULL);
+
+ char mem[10];
+ pwrite64 (tempfd, mem, sizeof (mem), 0);
+
+ pthread_cleanup_pop (0);
+
+ printf ("%s: pwrite64 returned\n", __FUNCTION__);
+
+ exit (1);
+}
static void *
tf_fsync (void *arg)
@@ -2140,10 +2280,13 @@ static struct
ADD_TEST (recv, 2, 0),
ADD_TEST (recvfrom, 2, 0),
ADD_TEST (recvmsg, 2, 0),
- ADD_TEST (open, 2, 1),
+ ADD_TEST (open, 2, 0),
+ ADD_TEST (open64, 2, 0),
ADD_TEST (close, 2, 1),
ADD_TEST (pread, 2, 1),
+ ADD_TEST (pread64, 2, 1),
ADD_TEST (pwrite, 2, 1),
+ ADD_TEST (pwrite64, 2, 1),
ADD_TEST (fsync, 2, 1),
ADD_TEST (fdatasync, 2, 1),
ADD_TEST (msync, 2, 1),
@@ -2185,6 +2328,12 @@ do_test (void)
}
setsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));
+ if (mktemp (fifoname) == NULL)
+ {
+ printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+ exit (1);
+ }
+
int result = 0;
size_t cnt;
for (cnt = 0; cnt < ntest_tf; ++cnt)