1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-01 10:06:57 +03:00

htl: Enable more tests

* htl/Makefile: Remove rules adding libpthread.so and libpthread.a to link
lines.
* nptl/Makefile: Move rules adding libpthread.so and libpthread.a to
link lines to...
* sysdeps/pthread/Makefile: ... here.

* nptl/eintr.c, tst-align.c tst-align3.c tst-atfork1.c tst-backtrace1.c
tst-bad-schedattr.c tst-cancel-self-canceltype.c tst-cancel-self-cleanup.c
tst-cancel-self-testcancel.c tst-cancel1.c tst-cancel10.c tst-cancel12.c
tst-cancel14.c tst-cancel15.c tst-cancel18.c tst-cancel19.c tst-cancel2.c
tst-cancel22.c tst-cancel23.c tst-cancel26.c tst-cancel27.c tst-cancel28.c
tst-cancel3.c tst-cancel8.c tst-cancelx1.c tst-cancelx10.c tst-cancelx12.c
tst-cancelx14.c tst-cancelx15.c tst-cancelx18.c tst-cancelx2.c tst-cancelx3.c
tst-cancelx8.c tst-cleanup0.c tst-cleanup0.expect tst-cleanup1.c tst-cleanup2.c
tst-cleanup3.c tst-cleanupx0.c tst-cleanupx0.expect tst-cleanupx1.c
tst-cleanupx2.c tst-cleanupx3.c tst-clock1.c tst-create-detached.c tst-detach1.c
tst-eintr2.c tst-eintr3.c tst-eintr4.c tst-eintr5.c tst-exec1.c tst-exec2.c
tst-exec3.c tst-exit1.c tst-exit2.c tst-exit3.c tst-flock1.c tst-fork1.c
tst-fork2.c tst-fork3.c tst-fork4.c tst-getpid3.c tst-kill1.c tst-kill2.c
tst-kill3.c tst-kill4.c tst-kill5.c tst-kill6.c tst-locale1.c tst-locale2.c
tst-memstream.c tst-popen1.c tst-raise1.c tst-sem5.c tst-setuid3.c tst-signal4.c
tst-signal5.c tst-signal6.c tst-signal8.c tst-stack1.c tst-stdio1.c tst-stdio2.c
tst-sysconf.c tst-tls1.c tst-tls2.c tst-tsd1.c tst-tsd2.c tst-tsd5.c tst-tsd6.c
tst-umask1.c tst-unload.c tst-unwind-thread.c tst-vfork1.c tst-vfork1x.c
tst-vfork2.c tst-vfork2x.c: Move tests to...
* sysdeps/pthread: ... here.
Rename
tst-popen1.c -> tst-pt-popen1.c
tst-align.c -> tst-pt-align.c
tst-align3.c -> tst-pt-align3.c
tst-sysconf.c -> tst-pt-sysconf.c
tst-tls1.c -> tst-pt-tls1.c
tst-tls2.c -> tst-pt-tls2.c
tst-vfork1.c -> tst-pt-vfork1.c
tst-vfork2.c -> tst-pt-vfork2.c
to avoid conflicting with libio/tst-popen1.c, elf/tst-align.c,
posix/tst-sysconf.c, elf/tst-tls1.c, elf/tst-tls2.c, posix/tst-vfork1.c,
posix/tst-vfork2.c.

* nptl/Makefile: Move corresponding tests references and special rules to...
* sysdeps/pthread/Makefile: ... here.

* sysdeps/pthread/tst-stack1.c (do_test): Do not clamp stack size to
PTHREAD_STACK_MIN if not defined.

Tested on linux-x86_64 and hurd-i386
This commit is contained in:
Samuel Thibault
2020-06-07 02:03:45 +00:00
parent be22a151f3
commit d6d74ec16c
100 changed files with 141 additions and 111 deletions

View File

@ -42,23 +42,48 @@ libpthread-routines += thrd_create thrd_detach thrd_exit thrd_join \
tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
tst-cnd-timedwait tst-thrd-detach tst-mtx-basic tst-thrd-sleep \
tst-mtx-recursive tst-tss-basic tst-call-once tst-mtx-timedlock \
\
tst-abstime \
tst-pt-align tst-pt-align3 \
tst-attr1 \
tst-backtrace1 \
tst-bad-schedattr \
tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \
tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \
tst-basic7 \
tst-cancel-self-canceltype tst-cancel-self-testcancel \
tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel8 tst-cancel10 \
tst-cancel12 tst-cancel14 tst-cancel15 tst-cancel18 tst-cancel19 \
tst-cancel22 tst-cancel23 tst-cancel26 tst-cancel27 tst-cancel28 \
tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 \
tst-clock1 \
tst-cond-except \
tst-cond1 tst-cond2 tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 \
tst-cond8 tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13 \
tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \
tst-cond20 tst-cond21 tst-cond23 tst-cond24 tst-cond25 tst-cond27 \
tst-cond-except \
tst-create-detached \
tst-detach1 \
tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \
tst-exec1 tst-exec2 tst-exec3 \
tst-exit1 tst-exit2 tst-exit3 \
tst-flock1 \
tst-fork1 tst-fork2 tst-fork3 tst-fork4 \
tst-atfork1 \
tst-getpid3 \
tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 tst-join7 \
tst-join8 tst-join9 tst-join10 tst-join11 tst-join12 tst-join13 \
tst-join14 \
tst-key1 tst-key2 tst-key3 tst-key4 \
tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
tst-locale1 tst-locale2 \
tst-memstream \
tst-mutex-errorcheck tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 \
tst-mutex5 tst-mutex6 tst-mutex7 tst-mutex7robust tst-mutex9 \
tst-mutex10 tst-mutex11 tst-pthread-mutexattr \
tst-once1 tst-once2 tst-once3 tst-once4 \
tst-pt-popen1 \
tst-raise1 \
tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \
tst-robust6 tst-robust7 tst-robust9 tst-robust10 \
tst-rwlock1 tst-rwlock4 tst-rwlock5 tst-rwlock12 \
@ -66,8 +91,79 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
tst-rwlock-tryrdlock-stall tst-rwlock-trywrlock-stall \
tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \
tst-sem8 tst-sem9 tst-sem10 tst-sem14 tst-sem15 tst-sem16 \
tst-setuid3 \
tst-signal4 tst-signal5 tst-signal6 tst-signal8 \
tst-spin1 tst-spin2 tst-spin3 tst-spin4 \
tst-abstime
tst-stack1 \
tst-stdio1 tst-stdio2 \
tst-pt-sysconf \
tst-pt-tls1 tst-pt-tls2 \
tst-tsd1 tst-tsd2 tst-tsd5 tst-tsd6 \
tst-umask1 \
tst-unload \
tst-unwind-thread \
tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \
# Files which must not be linked with libpthread.
tests-nolibpthread = tst-unload
# GCC-4.9 compiles 'sprintf(NULL, ...)' into UD2 on x86_64 without -fno-builtin
CFLAGS-tst-cleanup2.c += -fno-builtin
CFLAGS-tst-cleanupx2.c += -fno-builtin
tests += tst-cancelx2 tst-cancelx3 tst-cancelx8 tst-cancelx10 \
tst-cancelx12 tst-cancelx14 tst-cancelx15 tst-cancelx18 \
tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3
tests-static += tst-locale1 tst-locale2
tests += tst-cond11-static
# These tests are linked with libc before libpthread
tests-reverse += tst-cancel23 tst-vfork1x tst-vfork2x
ifeq ($(run-built-tests),yes)
ifeq ($(build-shared),yes)
tests-special += $(objpfx)tst-cleanup0-cmp.out
endif
endif
# Run the cancellation and cleanup tests also for the modern, exception-based
# implementation. For this we have to pass the -fexceptions parameter.
CFLAGS-tst-cancelx2.c += -fexceptions
CFLAGS-tst-cancelx3.c += -fexceptions
CFLAGS-tst-cancelx8.c += -fexceptions
CFLAGS-tst-cancelx10.c += -fexceptions
CFLAGS-tst-cancelx12.c += -fexceptions
CFLAGS-tst-cancelx14.c += -fexceptions
CFLAGS-tst-cancelx15.c += -fexceptions
CFLAGS-tst-cancelx18.c += -fexceptions
CFLAGS-tst-cleanupx0.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-tst-cleanupx1.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-tst-cleanupx2.c += -fexceptions
CFLAGS-tst-cleanupx3.c += -fexceptions
CFLAGS-tst-pt-align.c += $(stack-align-test-flags)
CFLAGS-tst-pt-align3.c += $(stack-align-test-flags)
tst-umask1-ARGS = $(objpfx)tst-umask1.temp
ifeq ($(build-shared),yes)
$(objpfx)tst-cleanup0.out: /dev/null $(objpfx)tst-cleanup0
$(make-test-out) > $@ 2>&1; \
$(evaluate-test)
$(objpfx)tst-cleanup0-cmp.out: $(..)sysdeps/pthread/tst-cleanup0.expect $(objpfx)tst-cleanup0.out
cmp $^ > $@; \
$(evaluate-test)
$(objpfx)tst-cancel28: $(common-objpfx)rt/librt.so
else
$(objpfx)tst-cancel28: $(common-objpfx)rt/librt.a
endif
tests-internal += tst-robust8
@ -88,4 +184,24 @@ $(objpfx)tst-join7.out: $(objpfx)tst-join7mod.so
$(objpfx)tst-join7mod.so: $(shared-thread-library)
LDFLAGS-tst-join7mod.so = -Wl,-soname,tst-join7mod.so
CFLAGS-tst-unwind-thread.c += -funwind-tables
# Make sure we link with the thread library.
ifeq ($(build-shared),yes)
$(addprefix $(objpfx), \
$(filter-out $(tests-static) $(xtests-static) $(tests-reverse) \
$(tests-nolibpthread), \
$(tests) $(tests-internal) $(xtests) $(test-srcs) $(tests-container))): \
$(objpfx)libpthread.so
$(objpfx)tst-unload: $(libdl)
# $(objpfx)../libc.so is used instead of $(common-objpfx)libc.so,
# since otherwise libpthread.so comes before libc.so when linking.
$(addprefix $(objpfx), $(tests-reverse)): \
$(objpfx)../libc.so $(objpfx)libpthread.so
$(objpfx)../libc.so: $(common-objpfx)libc.so ;
$(addprefix $(objpfx),$(tests-static) $(xtests-static)): $(objpfx)libpthread.a
else
$(addprefix $(objpfx),$(tests) $(test-srcs)): $(objpfx)libpthread.a
endif
endif

86
sysdeps/pthread/eintr.c Normal file
View File

@ -0,0 +1,86 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <support/xthread.h>
#include <support/xsignal.h>
#include <support/xthread.h>
static int the_sig;
static void
eintr_handler (int sig)
{
if (sig != the_sig)
{
write (STDOUT_FILENO, "eintr_handler: signal number wrong\n", 35);
_exit (1);
}
write (STDOUT_FILENO, ".", 1);
}
static void *
eintr_source (void *arg)
{
struct timespec ts = { .tv_sec = 0, .tv_nsec = 500000 };
if (arg == NULL)
{
sigset_t ss;
sigemptyset (&ss);
sigaddset (&ss, the_sig);
xpthread_sigmask (SIG_BLOCK, &ss, NULL);
}
while (1)
{
if (arg != NULL)
pthread_kill (*(pthread_t *) arg, the_sig);
else
kill (getpid (), the_sig);
nanosleep (&ts, NULL);
}
/* NOTREACHED */
return NULL;
}
static void
setup_eintr (int sig, pthread_t *thp)
{
struct sigaction sa;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = eintr_handler;
if (sigaction (sig, &sa, NULL) != 0)
{
puts ("setup_eintr: sigaction failed");
exit (1);
}
the_sig = sig;
/* Create the thread which will fire off the signals. */
xpthread_create (NULL, eintr_source, thp);
}

View File

@ -0,0 +1,120 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
static int val;
static void
prepare1 (void)
{
val *= 2;
}
static void
prepare2 (void)
{
++val;
}
static void
parent1 (void)
{
val += 4;
}
static void
parent2 (void)
{
val *= 4;
}
static void
child1 (void)
{
val += 8;
}
static void
child2 (void)
{
val *= 8;
}
static int
do_test (void)
{
pid_t pid;
int status = 0;
if (pthread_atfork (prepare1, parent1, child1) != 0)
{
puts ("1st atfork failed");
exit (1);
}
if (pthread_atfork (prepare2, parent2, child2) != 0)
{
puts ("2nd atfork failed");
exit (1);
}
pid = fork ();
if (pid == -1)
{
puts ("fork failed");
exit (1);
}
if (pid != 0)
{
/* Parent. */
if (val != 24)
{
printf ("expected val=%d, got %d\n", 24, val);
exit (1);
}
if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
{
puts ("waitpid failed");
exit (1);
}
}
else
{
/* Child. */
if (val != 80)
{
printf ("expected val=%d, got %d\n", 80, val);
exit (2);
}
}
return status;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,85 @@
/* Copyright (C) 2004-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2004.
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
<https://www.gnu.org/licenses/>. */
#include <execinfo.h>
#include <pthread.h>
#include <stdio.h>
#define BT_SIZE 64
void *bt_array[BT_SIZE];
int bt_cnt;
int
do_bt (void)
{
bt_cnt = backtrace (bt_array, BT_SIZE);
return 56;
}
int
call_do_bt (void)
{
return do_bt () + 1;
}
void *
tf (void *arg)
{
if (call_do_bt () != 57)
return (void *) 1L;
return NULL;
}
int
do_test (void)
{
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL))
{
puts ("create failed");
return 1;
}
void *res;
if (pthread_join (th, &res))
{
puts ("join failed");
return 1;
}
if (res != NULL)
{
puts ("thread failed");
return 1;
}
char **text = backtrace_symbols (bt_array, bt_cnt);
if (text == NULL)
{
puts ("backtrace_symbols failed");
return 1;
}
for (int i = 0; i < bt_cnt; ++i)
puts (text[i]);
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,97 @@
/* Test that pthread_create diagnoses invalid scheduling parameters.
Copyright (C) 2014-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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
<https://www.gnu.org/licenses/>. */
#include <assert.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void *
thread_function (void *arg)
{
abort ();
}
static int
do_test (void)
{
#if !defined SCHED_FIFO || !defined SCHED_OTHER
puts ("SCHED_FIFO or SCHED_OTHER not available at compile time");
return 0; /* 77 */
#else
int err;
#define TRY(func, arglist) \
if ((err = func arglist) != 0) \
{ \
printf ("%s: %s\n", #func, strerror (err)); \
return 2; \
}
int fifo_max = sched_get_priority_max (SCHED_FIFO);
if (fifo_max == -1)
{
assert (errno == ENOTSUP || errno == ENOSYS);
puts ("SCHED_FIFO not supported, cannot test");
return 0; /* 77 */
}
int other_max = sched_get_priority_max (SCHED_OTHER);
if (other_max == -1)
{
assert (errno == ENOTSUP || errno == ENOSYS);
puts ("SCHED_OTHER not supported, cannot test");
return 0; /* 77 */
}
assert (fifo_max > other_max);
pthread_attr_t attr;
TRY (pthread_attr_init, (&attr));
TRY (pthread_attr_setinheritsched, (&attr, PTHREAD_EXPLICIT_SCHED));
TRY (pthread_attr_setschedpolicy, (&attr, SCHED_FIFO));
/* This value is chosen so as to be valid for SCHED_FIFO but invalid for
SCHED_OTHER. */
struct sched_param param = { .sched_priority = other_max + 1 };
TRY (pthread_attr_setschedparam, (&attr, &param));
TRY (pthread_attr_setschedpolicy, (&attr, SCHED_OTHER));
/* Now ATTR has a sched_param that is invalid for its policy. */
pthread_t th;
err = pthread_create (&th, &attr, &thread_function, NULL);
if (err != EINVAL)
{
printf ("pthread_create returned %d (%s), expected %d (EINVAL: %s)\n",
err, strerror (err), EINVAL, strerror (EINVAL));
return 1;
}
return 0;
#endif
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,53 @@
/* Copyright (C) 2012-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tst-cancel-self-cleanup.c"
static int
do_test (void)
{
int ret = 0, should_fail = 0;
pthread_cleanup_push (cleanup, &should_fail);
if ((ret = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) != 0)
{
printf ("setcanceltype failed: %s\n", strerror (ret));
exit (1);
}
if ((ret = pthread_cancel (pthread_self ())) != 0)
{
printf ("cancel failed: %s\n", strerror (ret));
exit (1);
}
/* Wait to be canceled. Don't give any cancellation points to play with. */
while (1);
pthread_cleanup_pop (0);
return 1;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,23 @@
/* Copyright (C) 2012-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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
<https://www.gnu.org/licenses/>. */
static void
cleanup (void *cleanup_should_fail)
{
printf ("Main thread got cancelled and is being cleaned up now\n");
exit (*(int *)cleanup_should_fail);
}

View File

@ -0,0 +1,48 @@
/* Copyright (C) 2012-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tst-cancel-self-cleanup.c"
static int
do_test (void)
{
int ret = 0, should_fail = 0;
pthread_cleanup_push (cleanup, &should_fail);
if ((ret = pthread_cancel (pthread_self ())) != 0)
{
printf ("cancel failed: %s\n", strerror (ret));
exit (1);
}
pthread_testcancel ();
printf ("Could not cancel self.\n");
pthread_cleanup_pop (0);
return 1;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,162 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
static int cntr;
static void
cleanup (void *arg)
{
if (arg != (void *) 42l)
cntr = 42;
else
cntr = 1;
}
static void *
tf (void *arg)
{
/* Ignore all signals. This must not have any effect on delivering
the cancellation signal. */
sigset_t ss;
sigfillset (&ss);
if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
{
puts ("pthread_sigmask failed");
exit (1);
}
pthread_cleanup_push (cleanup, (void *) 42l);
int err = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
if (err != 0)
{
printf ("setcanceltype failed: %s\n", strerror (err));
exit (1);
}
/* The following code is not standard compliant: the mutex functions
must not be called with asynchronous cancellation enabled. */
err = pthread_mutex_unlock (&m2);
if (err != 0)
{
printf ("child: mutex_unlock failed: %s\n", strerror (err));
exit (1);
}
err = pthread_mutex_lock (&m1);
if (err != 0)
{
printf ("child: 1st mutex_lock failed: %s\n", strerror (err));
exit (1);
}
/* We should never come here. */
pthread_cleanup_pop (0);
return NULL;
}
static int
do_test (void)
{
int err;
pthread_t th;
int result = 0;
void *retval;
/* Get the mutexes. */
err = pthread_mutex_lock (&m1);
if (err != 0)
{
printf ("parent: 1st mutex_lock failed: %s\n", strerror (err));
return 1;
}
err = pthread_mutex_lock (&m2);
if (err != 0)
{
printf ("parent: 2nd mutex_lock failed: %s\n", strerror (err));
return 1;
}
err = pthread_create (&th, NULL, tf, NULL);
if (err != 0)
{
printf ("create failed: %s\n", strerror (err));
return 1;
}
err = pthread_mutex_lock (&m2);
if (err != 0)
{
printf ("parent: 3rd mutex_lock failed: %s\n", strerror (err));
return 1;
}
err = pthread_cancel (th);
if (err != 0)
{
printf ("cancel failed: %s\n", strerror (err));
return 1;
}
err = pthread_join (th, &retval);
if (err != 0)
{
printf ("join failed: %s\n", strerror (err));
return 1;
}
if (retval != PTHREAD_CANCELED)
{
printf ("wrong return value: %p\n", retval);
result = 1;
}
if (cntr == 42)
{
puts ("cleanup handler called with wrong argument");
result = 1;
}
else if (cntr != 1)
{
puts ("cleanup handling not called");
result = 1;
}
return result;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,125 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void
cleanup (void *arg)
{
/* Just for fun. */
if (pthread_cancel (pthread_self ()) != 0)
{
puts ("cleanup: cancel failed");
exit (1);
}
printf ("cleanup for %ld\n", (long int) arg);
}
static void *
tf (void *arg)
{
long int n = (long int) arg;
pthread_cleanup_push (cleanup, arg);
if (pthread_setcanceltype ((n & 1) == 0
? PTHREAD_CANCEL_DEFERRED
: PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0)
{
puts ("setcanceltype failed");
exit (1);
}
if (pthread_cancel (pthread_self ()) != 0)
{
puts ("cancel failed");
exit (1);
}
pthread_testcancel ();
/* We should never come here. */
pthread_cleanup_pop (0);
return NULL;
}
static int
do_test (void)
{
pthread_attr_t at;
if (pthread_attr_init (&at) != 0)
{
puts ("attr_init failed");
return 1;
}
if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
{
puts ("attr_setstacksize failed");
return 1;
}
#define N 20
int i;
pthread_t th[N];
for (i = 0; i < N; ++i)
if (pthread_create (&th[i], &at, tf, (void *) (long int) i) != 0)
{
puts ("create failed");
exit (1);
}
if (pthread_attr_destroy (&at) != 0)
{
puts ("attr_destroy failed");
return 1;
}
for (i = 0; i < N; ++i)
{
void *r;
if (pthread_join (th[i], &r) != 0)
{
puts ("join failed");
exit (1);
}
if (r != PTHREAD_CANCELED)
{
puts ("thread not canceled");
exit (1);
}
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,123 @@
/* Test sem_wait cancellation for uncontended case.
Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static pthread_barrier_t bar;
static sem_t sem;
static void
cleanup (void *arg)
{
static int ncall;
if (++ncall != 1)
{
puts ("second call to cleanup");
exit (1);
}
}
static void *
tf (void *arg)
{
pthread_cleanup_push (cleanup, NULL);
int e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("error: tf: 1st barrier_wait failed");
exit (1);
}
/* This call should be cancelable. */
sem_wait (&sem);
pthread_cleanup_pop (0);
return NULL;
}
static int
do_test (void)
{
pthread_t th;
if (pthread_barrier_init (&bar, NULL, 2) != 0)
{
puts ("error: barrier_init failed");
exit (1);
}
/* A value higher than 0 will check for uncontended pthread cancellation,
where the sem_wait operation will return immediatelly. */
if (sem_init (&sem, 0, 1) != 0)
{
puts ("error: sem_init failed");
exit (1);
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("error: create failed");
exit (1);
}
if (pthread_cancel (th) != 0)
{
puts ("error: pthread_cancel failed");
exit (1);
}
int e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("error: 1st barrier_wait failed");
exit (1);
}
void *r;
if (pthread_join (th, &r) != 0)
{
puts ("error: pthread_join failed");
exit (1);
}
if (r != PTHREAD_CANCELED)
{
puts ("error: thread not canceled");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,133 @@
/* Test sem_timedwait cancellation for uncontended case.
Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
static pthread_barrier_t bar;
static sem_t sem;
static void
cleanup (void *arg)
{
static int ncall;
if (++ncall != 1)
{
puts ("second call to cleanup");
exit (1);
}
}
static void *
tf (void *arg)
{
pthread_cleanup_push (cleanup, NULL);
int e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("error: tf: 1st barrier_wait failed");
exit (1);
}
struct timeval tv;
(void) gettimeofday (&tv, NULL);
struct timespec ts;
TIMEVAL_TO_TIMESPEC (&tv, &ts);
/* Timeout in 5 seconds. */
ts.tv_sec += 5;
/* This call should block and be cancelable. */
sem_timedwait (&sem, &ts);
pthread_cleanup_pop (0);
return NULL;
}
static int
do_test (void)
{
pthread_t th;
if (pthread_barrier_init (&bar, NULL, 2) != 0)
{
puts ("error: barrier_init failed");
exit (1);
}
if (sem_init (&sem, 0, 1) != 0)
{
puts ("error: sem_init failed");
exit (1);
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("error: create failed");
exit (1);
}
/* Check whether cancellation is honored even before sem_timedwait does
anything. */
if (pthread_cancel (th) != 0)
{
puts ("error: 1st cancel failed");
exit (1);
}
int e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("1st barrier_wait failed");
exit (1);
}
void *r;
if (pthread_join (th, &r) != 0)
{
puts ("join failed");
exit (1);
}
if (r != PTHREAD_CANCELED)
{
puts ("thread not canceled");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,138 @@
/* Test sem_timedwait cancellation for contended case.
Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
static pthread_barrier_t bar;
static sem_t sem;
static void
cleanup (void *arg)
{
static int ncall;
if (++ncall != 1)
{
puts ("second call to cleanup");
exit (1);
}
}
static void *
tf (void *arg)
{
int e;
pthread_cleanup_push (cleanup, NULL);
e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("error: tf: 1st barrier_wait failed");
exit (1);
}
struct timeval tv;
(void) gettimeofday (&tv, NULL);
struct timespec ts;
TIMEVAL_TO_TIMESPEC (&tv, &ts);
/* Timeout in 5 seconds. */
ts.tv_sec += 5;
/* This call should block and be cancelable. */
errno = 0;
e = sem_timedwait (&sem, &ts);
pthread_cleanup_pop (0);
return NULL;
}
static int
do_test (void)
{
pthread_t th;
if (pthread_barrier_init (&bar, NULL, 2) != 0)
{
puts ("error: barrier_init failed");
exit (1);
}
if (sem_init (&sem, 0, 0) != 0)
{
puts ("error: sem_init failed");
exit (1);
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("error: create failed");
exit (1);
}
int e = pthread_barrier_wait (&bar);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("error: 1st barrier_wait failed");
exit (1);
}
/* Give the child a chance to go to sleep in sem_wait. */
sleep (1);
/* Check whether cancellation is honored when waiting in sem_timedwait. */
if (pthread_cancel (th) != 0)
{
puts ("error: 1st cancel failed");
exit (1);
}
void *r;
if (pthread_join (th, &r) != 0)
{
puts ("error: join failed");
exit (1);
}
if (r != PTHREAD_CANCELED)
{
puts ("error: thread not canceled");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,173 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
static pthread_barrier_t b;
/* Cleanup handling test. */
static int cl_called;
static void
cl (void *arg)
{
++cl_called;
}
static void *
tf (void *arg)
{
int r = pthread_barrier_wait (&b);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
pthread_cleanup_push (cl, NULL);
struct timespec ts = { .tv_sec = arg == NULL ? 10000000 : 0, .tv_nsec = 0 };
TEMP_FAILURE_RETRY (clock_nanosleep (CLOCK_REALTIME, 0, &ts, &ts));
pthread_cleanup_pop (0);
puts ("clock_nanosleep returned");
exit (1);
}
static int
do_test (void)
{
if (pthread_barrier_init (&b, NULL, 2) != 0)
{
puts ("barrier_init failed");
return 1;
}
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("1st create failed");
return 1;
}
int r = pthread_barrier_wait (&b);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
while (nanosleep (&ts, &ts) != 0)
continue;
puts ("going to cancel in-time");
if (pthread_cancel (th) != 0)
{
puts ("1st cancel failed");
return 1;
}
void *status;
if (pthread_join (th, &status) != 0)
{
puts ("1st join failed");
return 1;
}
if (status != PTHREAD_CANCELED)
{
puts ("1st thread not canceled");
return 1;
}
if (cl_called == 0)
{
puts ("cleanup handler not called");
return 1;
}
if (cl_called > 1)
{
puts ("cleanup handler called more than once");
return 1;
}
puts ("in-time cancellation succeeded");
cl_called = 0;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("2nd create failed");
return 1;
}
puts ("going to cancel early");
if (pthread_cancel (th) != 0)
{
puts ("2nd cancel failed");
return 1;
}
r = pthread_barrier_wait (&b);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
if (pthread_join (th, &status) != 0)
{
puts ("2nd join failed");
return 1;
}
if (status != PTHREAD_CANCELED)
{
puts ("2nd thread not canceled");
return 1;
}
if (cl_called == 0)
{
printf ("cleanup handler not called\n");
return 1;
}
if (cl_called > 1)
{
printf ("cleanup handler called more than once\n");
return 1;
}
puts ("early cancellation succeeded");
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,285 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <unistd.h>
static void *
tf (void *arg)
{
return NULL;
}
static void
handler (int sig)
{
}
static void __attribute__ ((noinline))
clobber_lots_of_regs (void)
{
#define X1(n) long r##n = 10##n; __asm __volatile ("" : "+r" (r##n));
#define X2(n) X1(n##0) X1(n##1) X1(n##2) X1(n##3) X1(n##4)
#define X3(n) X2(n##0) X2(n##1) X2(n##2) X2(n##3) X2(n##4)
X3(0) X3(1) X3(2) X3(3) X3(4)
#undef X1
#define X1(n) __asm __volatile ("" : : "r" (r##n));
X3(0) X3(1) X3(2) X3(3) X3(4)
#undef X1
#undef X2
#undef X3
}
static int
do_test (void)
{
pthread_t th;
int old, rc;
int ret = 0;
int fd[2];
rc = pipe (fd);
if (rc < 0)
error (EXIT_FAILURE, errno, "couldn't create pipe");
rc = pthread_create (&th, NULL, tf, NULL);
if (rc)
error (EXIT_FAILURE, rc, "couldn't create thread");
rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
if (rc)
{
error (0, rc, "1st pthread_setcanceltype failed");
ret = 1;
}
if (old != PTHREAD_CANCEL_DEFERRED && old != PTHREAD_CANCEL_ASYNCHRONOUS)
{
error (0, 0, "1st pthread_setcanceltype returned invalid value %d",
old);
ret = 1;
}
clobber_lots_of_regs ();
close (fd[0]);
rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
if (rc)
{
error (0, rc, "pthread_setcanceltype after close failed");
ret = 1;
}
if (old != PTHREAD_CANCEL_DEFERRED)
{
error (0, 0, "pthread_setcanceltype after close returned invalid value %d",
old);
ret = 1;
}
clobber_lots_of_regs ();
close (fd[1]);
rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
if (rc)
{
error (0, rc, "pthread_setcanceltype after 2nd close failed");
ret = 1;
}
if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
{
error (0, 0, "pthread_setcanceltype after 2nd close returned invalid value %d",
old);
ret = 1;
}
struct sigaction sa = { .sa_handler = handler, .sa_flags = 0 };
sigemptyset (&sa.sa_mask);
sigaction (SIGALRM, &sa, NULL);
struct itimerval it;
it.it_value.tv_sec = 1;
it.it_value.tv_usec = 0;
it.it_interval = it.it_value;
setitimer (ITIMER_REAL, &it, NULL);
clobber_lots_of_regs ();
pause ();
memset (&it, 0, sizeof (it));
setitimer (ITIMER_REAL, &it, NULL);
rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
if (rc)
{
error (0, rc, "pthread_setcanceltype after pause failed");
ret = 1;
}
if (old != PTHREAD_CANCEL_DEFERRED)
{
error (0, 0, "pthread_setcanceltype after pause returned invalid value %d",
old);
ret = 1;
}
it.it_value.tv_sec = 1;
it.it_value.tv_usec = 0;
it.it_interval = it.it_value;
setitimer (ITIMER_REAL, &it, NULL);
clobber_lots_of_regs ();
pause ();
memset (&it, 0, sizeof (it));
setitimer (ITIMER_REAL, &it, NULL);
rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
if (rc)
{
error (0, rc, "pthread_setcanceltype after 2nd pause failed");
ret = 1;
}
if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
{
error (0, 0, "pthread_setcanceltype after 2nd pause returned invalid value %d",
old);
ret = 1;
}
char fname[] = "/tmp/tst-cancel19-dir-XXXXXX\0foo/bar";
char *enddir = strchr (fname, '\0');
if (mkdtemp (fname) == NULL)
{
error (0, errno, "mkdtemp failed");
ret = 1;
}
*enddir = '/';
clobber_lots_of_regs ();
creat (fname, 0400);
rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
if (rc)
{
error (0, rc, "pthread_setcanceltype after creat failed");
ret = 1;
}
if (old != PTHREAD_CANCEL_DEFERRED)
{
error (0, 0, "pthread_setcanceltype after creat returned invalid value %d",
old);
ret = 1;
}
clobber_lots_of_regs ();
creat (fname, 0400);
rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
if (rc)
{
error (0, rc, "pthread_setcanceltype after 2nd creat failed");
ret = 1;
}
if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
{
error (0, 0, "pthread_setcanceltype after 2nd creat returned invalid value %d",
old);
ret = 1;
}
clobber_lots_of_regs ();
open (fname, O_CREAT, 0400);
rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
if (rc)
{
error (0, rc, "pthread_setcanceltype after open failed");
ret = 1;
}
if (old != PTHREAD_CANCEL_DEFERRED)
{
error (0, 0, "pthread_setcanceltype after open returned invalid value %d",
old);
ret = 1;
}
clobber_lots_of_regs ();
open (fname, O_CREAT, 0400);
rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
if (rc)
{
error (0, rc, "pthread_setcanceltype after 2nd open failed");
ret = 1;
}
if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
{
error (0, 0, "pthread_setcanceltype after 2nd open returned invalid value %d",
old);
ret = 1;
}
*enddir = '\0';
rmdir (fname);
clobber_lots_of_regs ();
select (-1, NULL, NULL, NULL, NULL);
rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
if (rc)
{
error (0, rc, "pthread_setcanceltype after select failed");
ret = 1;
}
if (old != PTHREAD_CANCEL_DEFERRED)
{
error (0, 0, "pthread_setcanceltype after select returned invalid value %d",
old);
ret = 1;
}
clobber_lots_of_regs ();
select (-1, NULL, NULL, NULL, NULL);
rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
if (rc)
{
error (0, rc, "pthread_setcanceltype after 2nd select failed");
ret = 1;
}
if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
{
error (0, 0, "pthread_setcanceltype after 2nd select returned invalid value %d",
old);
ret = 1;
}
pthread_join (th, NULL);
return ret;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,95 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
static int fd[2];
static void *
tf (void *arg)
{
/* The buffer size must be larger than the pipe size so that the
write blocks. */
char buf[100000];
while (write (fd[1], buf, sizeof (buf)) > 0);
return (void *) 42l;
}
static int
do_test (void)
{
pthread_t th;
void *r;
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction (SIGPIPE, &sa, NULL) != 0)
{
puts ("sigaction failed");
return 1;
}
if (pipe (fd) != 0)
{
puts ("pipe failed");
return 1;
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
return 1;
}
if (pthread_cancel (th) != 0)
{
puts ("cancel failed");
return 1;
}
/* This will cause the write in the child to return. */
close (fd[0]);
if (pthread_join (th, &r) != 0)
{
puts ("join failed");
return 1;
}
if (r != PTHREAD_CANCELED)
{
printf ("result is wrong: expected %p, got %p\n", PTHREAD_CANCELED, r);
return 1;
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,119 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_barrier_t b;
int seen;
static void *
tf (void *arg)
{
int old;
int r = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old);
if (r != 0)
{
puts ("setcancelstate failed");
exit (1);
}
r = pthread_barrier_wait (&b);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
for (int i = 0; i < 10; ++i)
{
struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
}
seen = 1;
pthread_setcancelstate (old, NULL);
struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
exit (1);
}
static int
do_test (void)
{
if (pthread_barrier_init (&b, NULL, 2) != 0)
{
puts ("barrier init failed");
return 1;
}
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("thread creation failed");
return 1;
}
int r = pthread_barrier_wait (&b);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
return 1;
}
if (pthread_cancel (th) != 0)
{
puts ("cancel failed");
return 1;
}
void *status;
if (pthread_join (th, &status) != 0)
{
puts ("join failed");
return 1;
}
if (status != PTHREAD_CANCELED)
{
puts ("thread not canceled");
return 1;
}
if (pthread_barrier_destroy (&b) != 0)
{
puts ("barrier_destroy failed");
return 1;
}
if (seen != 1)
{
puts ("thread cancelled when PTHREAD_CANCEL_DISABLED");
return 1;
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1 @@
#include "tst-cancel22.c"

View File

@ -0,0 +1,68 @@
/* Check for failure paths handling for cancellation points.
Copyright (C) 2015-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/* Check that the cancel syscall points handles both the errno and return code
correctly for invalid arguments. */
static void *
tf (void *arg)
{
#ifdef SET_CANCEL_DISABLE
pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
#endif
/* This is a cancellation point, but we should not be cancelled. */
int r = write (-1, 0, 0);
if (r != -1 || errno != EBADF)
{
printf ("error: write returned %d, errno %d\n", r, errno);
exit (1);
}
return NULL;
}
static int
do_test (void)
{
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("error: pthread_create failed");
exit (1);
}
if (pthread_join (th, NULL) != 0)
{
puts ("error: pthread_join failed");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,23 @@
/* Check for failure paths handling for cancellation points.
Copyright (C) 2015-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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
<https://www.gnu.org/licenses/>. */
/* Similar to tst-cancel26.c but with pthread cancel state set to
PTHREAD_CANCEL_DISABLE. */
#define SET_CANCEL_DISABLE 1
#include "tst-cancel26.c"

View File

@ -0,0 +1,79 @@
/* Check if the thread created by POSIX timer using SIGEV_THREAD is
cancellable.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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
<https://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#include <stdbool.h>
#include <support/check.h>
#include <support/test-driver.h>
#include <support/xthread.h>
static pthread_barrier_t barrier;
static pthread_t timer_thread;
static void
cl (void *arg)
{
xpthread_barrier_wait (&barrier);
}
static void
thread_handler (union sigval sv)
{
timer_thread = pthread_self ();
xpthread_barrier_wait (&barrier);
pthread_cleanup_push (cl, NULL);
while (1)
clock_nanosleep (CLOCK_REALTIME, 0, &(struct timespec) { 1, 0 }, NULL);
pthread_cleanup_pop (0);
}
static int
do_test (void)
{
struct sigevent sev = { 0 };
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = &thread_handler;
timer_t timerid;
TEST_COMPARE (timer_create (CLOCK_REALTIME, &sev, &timerid), 0);
xpthread_barrier_init (&barrier, NULL, 2);
struct itimerspec trigger = { 0 };
trigger.it_value.tv_nsec = 1000000;
TEST_COMPARE (timer_settime (timerid, 0, &trigger, NULL), 0);
xpthread_barrier_wait (&barrier);
xpthread_cancel (timer_thread);
xpthread_barrier_init (&barrier, NULL, 2);
xpthread_barrier_wait (&barrier);
return 0;
}
/* A stall in cancellation is a regression. */
#include <support/test-driver.c>

View File

@ -0,0 +1,97 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
static int fd[2];
static void *
tf (void *arg)
{
char buf[100];
if (read (fd[0], buf, sizeof (buf)) == sizeof (buf))
{
puts ("read succeeded");
return (void *) 1l;
}
return NULL;
}
static int
do_test (void)
{
pthread_t th;
void *r;
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction (SIGPIPE, &sa, NULL) != 0)
{
puts ("sigaction failed");
return 1;
}
if (pipe (fd) != 0)
{
puts ("pipe failed");
return 1;
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
return 1;
}
if (pthread_cancel (th) != 0)
{
puts ("cancel failed");
return 1;
}
/* This will cause the read in the child to return. */
close (fd[0]);
if (pthread_join (th, &r) != 0)
{
puts ("join failed");
return 1;
}
if (r != PTHREAD_CANCELED)
{
puts ("result is wrong");
return 1;
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,142 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static pthread_barrier_t bar;
static int global;
static void
cleanup (void *arg)
{
global = 1;
}
static void *
tf (void *arg)
{
/* Enable cancellation, but defer it. */
if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0)
{
puts ("setcancelstate failed");
exit (1);
}
if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
{
puts ("setcanceltype failed");
exit (1);
}
/* Add cleanup handler. */
pthread_cleanup_push (cleanup, NULL);
/* Synchronize with the main thread. */
int r = pthread_barrier_wait (&bar);
if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("tf: first barrier_wait failed");
exit (1);
}
/* And again. Once this is done the main thread should have canceled
this thread. */
r = pthread_barrier_wait (&bar);
if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("tf: second barrier_wait failed");
exit (1);
}
/* Remove the cleanup handler without executing it. */
pthread_cleanup_pop (0);
/* Now react on the cancellation. */
pthread_testcancel ();
/* This call should never return. */
return NULL;
}
static int
do_test (void)
{
if (pthread_barrier_init (&bar, NULL, 2) != 0)
{
puts ("barrier_init failed");
exit (1);
}
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("pthread_create failed");
return 1;
}
int r = pthread_barrier_wait (&bar);
if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("first barrier_wait failed");
exit (1);
}
if (pthread_cancel (th) != 0)
{
puts ("pthread_cancel failed");
return 1;
}
r = pthread_barrier_wait (&bar);
if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("second barrier_wait failed");
exit (1);
}
void *result;
if (pthread_join (th, &result) != 0)
{
puts ("pthread_join failed");
return 1;
}
if (result != PTHREAD_CANCELED)
{
puts ("thread was not canceled");
exit (1);
}
if (global != 0)
{
puts ("cancellation handler has been called");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1 @@
#include "tst-cancel1.c"

View File

@ -0,0 +1 @@
#include "tst-cancel10.c"

View File

@ -0,0 +1 @@
#include "tst-cancel12.c"

View File

@ -0,0 +1 @@
#include "tst-cancel14.c"

View File

@ -0,0 +1 @@
#include "tst-cancel15.c"

View File

@ -0,0 +1 @@
#include "tst-cancel18.c"

View File

@ -0,0 +1 @@
#include "tst-cancel2.c"

View File

@ -0,0 +1 @@
#include "tst-cancel3.c"

View File

@ -0,0 +1 @@
#include "tst-cancel8.c"

View File

@ -0,0 +1,74 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int global;
static void
ch (void *arg)
{
int val = (long int) arg;
printf ("ch (%d)\n", val);
global *= val;
global += val;
}
static void
endfct (void)
{
/* We force exit right here. */
_exit (global);
}
static int
do_test (void)
{
atexit (endfct);
pthread_cancel (pthread_self ());
pthread_cleanup_push (ch, (void *) 1l);
pthread_cleanup_push (ch, (void *) 2l);
pthread_cleanup_push (ch, (void *) 3l);
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_cleanup_pop (1);
pthread_cleanup_pop (1);
pthread_cleanup_pop (1);
return 100;
}
#define EXPECTED_STATUS 9
#include <support/test-driver.c>

View File

@ -0,0 +1,3 @@
ch (3)
ch (2)
ch (1)

View File

@ -0,0 +1,100 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int do_test (void);
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
static int global;
static void
ch (void *arg)
{
int val = (long int) arg;
printf ("ch (%d)\n", val);
global *= val;
global += val;
}
static void *
tf (void *a)
{
pthread_cancel (pthread_self ());
pthread_cleanup_push (ch, (void *) 1l);
pthread_cleanup_push (ch, (void *) 2l);
pthread_cleanup_push (ch, (void *) 3l);
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_cleanup_pop (1);
pthread_cleanup_pop (1);
pthread_cleanup_pop (1);
return NULL;
}
int
do_test (void)
{
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
write_message ("create failed\n");
_exit (1);
}
void *r;
int e;
if ((e = pthread_join (th, &r)) != 0)
{
printf ("join failed: %d\n", e);
_exit (1);
}
if (r != PTHREAD_CANCELED)
{
puts ("thread not canceled");
exit (1);
}
if (global != 9)
{
printf ("global = %d, expected 9\n", global);
exit (1);
}
return 0;
}

View File

@ -0,0 +1,63 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Bao Duong <bduong@progress.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
static sigjmp_buf jmpbuf;
static void
sig_handler (int signo)
{
siglongjmp (jmpbuf, 1);
}
static int
do_test (void)
{
char *p = NULL;
/* gcc can overwrite the success written value by scheduling instructions
around sprintf. It is allowed to do this since according to C99 the first
argument of sprintf is a character array and NULL is not a valid character
array. Mark the return value as volatile so that it gets reloaded on
return. */
volatile int ret = 0;
if (signal (SIGSEGV, &sig_handler) == SIG_ERR)
{
perror ("installing SIGSEGV handler");
return 1;
}
puts ("Attempting to sprintf to null ptr");
if (setjmp (jmpbuf))
{
puts ("Exiting main...");
return ret;
}
sprintf (p, "This should segv\n");
return 1;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,98 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int do_test (void);
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
static int global;
static void
ch (void *arg)
{
int val = (long int) arg;
printf ("ch (%d)\n", val);
global *= val;
global += val;
}
static void *
tf (void *a)
{
pthread_cleanup_push (ch, (void *) 1l);
pthread_cleanup_push (ch, (void *) 2l);
pthread_cleanup_push (ch, (void *) 3l);
pthread_exit ((void *) 1l);
pthread_cleanup_pop (1);
pthread_cleanup_pop (1);
pthread_cleanup_pop (1);
return NULL;
}
int
do_test (void)
{
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
write_message ("create failed\n");
_exit (1);
}
void *r;
int e;
if ((e = pthread_join (th, &r)) != 0)
{
printf ("join failed: %d\n", e);
_exit (1);
}
if (r != (void *) 1l)
{
puts ("thread not canceled");
exit (1);
}
if (global != 9)
{
printf ("global = %d, expected 9\n", global);
exit (1);
}
return 0;
}

View File

@ -0,0 +1 @@
#include "tst-cleanup0.c"

View File

@ -0,0 +1,3 @@
ch (3)
ch (2)
ch (1)

View File

@ -0,0 +1 @@
#include "tst-cleanup1.c"

View File

@ -0,0 +1 @@
#include "tst-cleanup2.c"

View File

@ -0,0 +1 @@
#include "tst-cleanup3.c"

View File

@ -0,0 +1,50 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int
do_test (void)
{
#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
clockid_t cl;
/* This is really only a linking-test here. */
int e = pthread_getcpuclockid (pthread_self (), &cl);
if (e != 0)
{
# if _POSIX_THREAD_CPUTIME == 0
if (sysconf (_SC_THREAD_CPUTIME) >= 0)
# endif
{
puts ("cpuclock advertized, but cannot get ID");
exit (1);
}
}
#endif
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -1,162 +0,0 @@
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
static pthread_barrier_t b;
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
static void
cl (void *arg)
{
pthread_mutex_unlock (&m);
}
static void *
tf (void *arg)
{
if (pthread_mutex_lock (&m) != 0)
{
printf ("%s: mutex_lock failed\n", __func__);
exit (1);
}
int e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
printf ("%s: barrier_wait failed\n", __func__);
exit (1);
}
pthread_cleanup_push (cl, NULL);
/* We have to loop here because the cancellation might come after
the cond_wait call left the cancelable area and is then waiting
on the mutex. In this case the beginning of the second cond_wait
call will cause the cancellation to happen. */
do
if (pthread_cond_wait (&c, &m) != 0)
{
printf ("%s: cond_wait failed\n", __func__);
exit (1);
}
while (arg == NULL);
pthread_cleanup_pop (0);
if (pthread_mutex_unlock (&m) != 0)
{
printf ("%s: mutex_unlock failed\n", __func__);
exit (1);
}
return NULL;
}
static int
do_test (void)
{
int status = 0;
if (pthread_barrier_init (&b, NULL, 2) != 0)
{
puts ("barrier_init failed");
return 1;
}
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("1st create failed");
return 1;
}
int e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("1st barrier_wait failed");
return 1;
}
if (pthread_mutex_lock (&m) != 0)
{
puts ("1st mutex_lock failed");
return 1;
}
if (pthread_cond_signal (&c) != 0)
{
puts ("1st cond_signal failed");
return 1;
}
if (pthread_cancel (th) != 0)
{
puts ("cancel failed");
return 1;
}
if (pthread_mutex_unlock (&m) != 0)
{
puts ("1st mutex_unlock failed");
return 1;
}
void *res;
if (pthread_join (th, &res) != 0)
{
puts ("1st join failed");
return 1;
}
if (res != PTHREAD_CANCELED)
{
puts ("first thread not canceled");
status = 1;
}
printf ("cond = { %llu, %llu, %u/%u/%u, %u/%u/%u, %u, %u }\n",
c.__data.__wseq, c.__data.__g1_start,
c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
c.__data.__g1_orig_size, c.__data.__wrefs);
if (pthread_create (&th, NULL, tf, (void *) 1l) != 0)
{
puts ("2nd create failed");
return 1;
}
e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("2nd barrier_wait failed");
return 1;
}
if (pthread_mutex_lock (&m) != 0)
{
puts ("2nd mutex_lock failed");
return 1;
}
if (pthread_cond_signal (&c) != 0)
{
puts ("2nd cond_signal failed");
return 1;
}
if (pthread_mutex_unlock (&m) != 0)
{
puts ("2nd mutex_unlock failed");
return 1;
}
if (pthread_join (th, &res) != 0)
{
puts ("2nd join failed");
return 1;
}
if (res != NULL)
{
puts ("2nd thread canceled");
status = 1;
}
printf ("cond = { %llu, %llu, %u/%u/%u, %u/%u/%u, %u, %u }\n",
c.__data.__wseq, c.__data.__g1_start,
c.__data.__g_signals[0], c.__data.__g_refs[0], c.__data.__g_size[0],
c.__data.__g_signals[1], c.__data.__g_refs[1], c.__data.__g_size[1],
c.__data.__g1_orig_size, c.__data.__wrefs);
return status;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -1,77 +0,0 @@
/* Test unsupported/bad clocks passed to pthread_cond_clockwait.
Copyright (C) 2019-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <support/check.h>
#include <support/timespec.h>
#include <support/xthread.h>
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
#define NOT_A_VALID_CLOCK 123456
static int
do_test (void)
{
xpthread_mutex_lock (&mut);
const struct timespec ts = make_timespec (0, 0);
/* These clocks are meaningless to sem_clockwait. */
#if defined(CLOCK_PROCESS_CPUTIME_ID)
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
CLOCK_PROCESS_CPUTIME_ID, &ts), EINVAL);
#endif
#if defined(CLOCK_THREAD_CPUTIME_ID)
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
CLOCK_THREAD_CPUTIME_ID, &ts), EINVAL);
#endif
/* These clocks might be meaningful, but are currently unsupported
by pthread_cond_clockwait. */
#if defined(CLOCK_REALTIME_COARSE)
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
CLOCK_REALTIME_COARSE, &ts), EINVAL);
#endif
#if defined(CLOCK_MONOTONIC_RAW)
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
CLOCK_MONOTONIC_RAW, &ts), EINVAL);
#endif
#if defined(CLOCK_MONOTONIC_COARSE)
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
CLOCK_MONOTONIC_COARSE, &ts), EINVAL);
#endif
#if defined(CLOCK_BOOTTIME)
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
CLOCK_BOOTTIME, &ts), EINVAL);
#endif
/* This is a completely invalid clock. */
TEST_COMPARE (pthread_cond_clockwait (&cond, &mut,
NOT_A_VALID_CLOCK, &ts), EINVAL);
return 0;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,138 @@
/* Bug 20116: Test rapid creation of detached threads.
Copyright (C) 2017-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
/* The goal of the test is to trigger a failure if the parent touches
any part of the thread descriptor after the detached thread has
exited. We test this by creating many detached threads with large
stacks. The stacks quickly fill the the stack cache and subsequent
threads will start to cause the thread stacks to be immediately
unmapped to satisfy the stack cache max. With the stacks being
unmapped the parent's read of any part of the thread descriptor will
trigger a segfault. That segfault is what we are trying to cause,
since any segfault is a defect in the implementation. */
#include <pthread.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/resource.h>
#include <support/xthread.h>
/* Number of threads to create. */
enum { threads_to_create = 100000 };
/* Number of threads which should spawn other threads. */
enum { creator_threads = 2 };
/* Counter of threads created so far. This is incremented by all the
running creator threads. */
static unsigned threads_created;
/* Thread callback which does nothing, so that the thread exits
immediatedly. */
static void *
do_nothing (void *arg)
{
return NULL;
}
/* Attribute indicating that the thread should be created in a detached
fashion. */
static pthread_attr_t detached;
/* Barrier to synchronize initialization. */
static pthread_barrier_t barrier;
static void *
creator_thread (void *arg)
{
int ret;
xpthread_barrier_wait (&barrier);
while (true)
{
pthread_t thr;
/* Thread creation will fail if the kernel does not free old
threads quickly enough, so we do not report errors. */
ret = pthread_create (&thr, &detached, do_nothing, NULL);
if (ret == 0 && __atomic_add_fetch (&threads_created, 1, __ATOMIC_SEQ_CST)
>= threads_to_create)
break;
}
return NULL;
}
static int
do_test (void)
{
/* Limit the size of the process, so that memory allocation will
fail without impacting the entire system. */
{
struct rlimit limit;
if (getrlimit (RLIMIT_AS, &limit) != 0)
{
printf ("FAIL: getrlimit (RLIMIT_AS) failed: %m\n");
return 1;
}
/* This limit, 800MB, is just a heuristic. Any value can be
picked. */
long target = 800 * 1024 * 1024;
if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > target)
{
limit.rlim_cur = target;
if (setrlimit (RLIMIT_AS, &limit) != 0)
{
printf ("FAIL: setrlimit (RLIMIT_AS) failed: %m\n");
return 1;
}
}
}
xpthread_attr_init (&detached);
xpthread_attr_setdetachstate (&detached, PTHREAD_CREATE_DETACHED);
/* A large thread stack seems beneficial for reproducing a race
condition in detached thread creation. The goal is to reach the
limit of the runtime thread stack cache such that the detached
thread's stack is unmapped after exit and causes a segfault when
the parent reads the thread descriptor data stored on the the
unmapped stack. */
xpthread_attr_setstacksize (&detached, 16 * 1024 * 1024);
xpthread_barrier_init (&barrier, NULL, creator_threads);
pthread_t threads[creator_threads];
for (int i = 0; i < creator_threads; ++i)
threads[i] = xpthread_create (NULL, creator_thread, NULL);
for (int i = 0; i < creator_threads; ++i)
xpthread_join (threads[i]);
xpthread_attr_destroy (&detached);
xpthread_barrier_destroy (&barrier);
return 0;
}
#define TIMEOUT 100
#include <support/test-driver.c>

View File

@ -0,0 +1,55 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static void *
tf (void *arg)
{
return NULL;
}
static int
do_test (void)
{
pthread_t th;
if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
{
puts ("create failed");
exit (1);
}
/* Give the child a chance to finish. */
sleep (1);
if (pthread_detach (th) != 0)
{
puts ("detach failed");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,88 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <support/check.h>
#include <support/timespec.h>
#include <support/xtime.h>
#include "eintr.c"
static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
static void *
tf1 (void *arg)
{
struct timespec ts = timespec_add (xclock_now (CLOCK_REALTIME),
make_timespec (10000, 0));
/* This call must never return. */
int e = pthread_mutex_timedlock (&m1, &ts);
char buf[100];
printf ("tf1: mutex_timedlock returned: %s\n",
strerror_r (e, buf, sizeof (buf)));
exit (1);
}
static void *
tf2 (void *arg)
{
while (1)
{
TEST_COMPARE (pthread_mutex_lock (&m2), 0);
TEST_COMPARE (pthread_mutex_unlock (&m2), 0);
struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
nanosleep (&ts, NULL);
}
return NULL;
}
static int
do_test (void)
{
TEST_COMPARE (pthread_mutex_lock (&m1), 0);
setup_eintr (SIGUSR1, NULL);
char buf[100];
xpthread_create (NULL, tf1, NULL);
xpthread_create (NULL, tf2, NULL);
delayed_exit (3);
/* This call must never return. */
int e = pthread_mutex_lock (&m1);
printf ("main: mutex_lock returned: %s\n",
strerror_r (e, buf, sizeof (buf)));
return 1;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,60 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <support/check.h>
#include <support/xthread.h>
#include "eintr.c"
static void *
tf (void *arg)
{
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
xpthread_mutex_lock (&m);
/* This call must not return. */
xpthread_mutex_lock (&m);
puts ("tf: mutex_lock returned");
exit (1);
}
static int
do_test (void)
{
pthread_t self = pthread_self ();
setup_eintr (SIGUSR1, &self);
pthread_t th = xpthread_create (NULL, tf, NULL);
delayed_exit (1);
/* This call must never return. */
xpthread_join (th);
puts ("error: pthread_join returned");
return 1;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,48 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <support/check.h>
#include <support/xthread.h>
#include "eintr.c"
static int
do_test (void)
{
pthread_t self = pthread_self ();
setup_eintr (SIGUSR1, &self);
pthread_barrier_t b;
xpthread_barrier_init (&b, NULL, 2);
delayed_exit (1);
/* This call must never return. */
xpthread_barrier_wait (&b);
puts ("error: pthread_barrier_wait returned");
return 1;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,63 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <support/check.h>
#include <support/timespec.h>
#include <support/xthread.h>
#include <support/xtime.h>
#include "eintr.c"
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
static void *
tf (void *arg)
{
struct timespec ts = timespec_add (xclock_now (CLOCK_REALTIME),
make_timespec (10000, 0));
/* This call must never return. */
TEST_COMPARE (pthread_cond_timedwait (&c, &m, &ts), 0);
FAIL_EXIT1 ("pthread_cond_timedwait returned unexpectedly\n");
}
static int
do_test (void)
{
setup_eintr (SIGUSR1, NULL);
xpthread_create (NULL, tf, NULL);
delayed_exit (3);
/* This call must never return. */
xpthread_cond_wait (&c, &m);
FAIL_RET ("error: pthread_cond_wait returned");
}
#include <support/test-driver.c>

156
sysdeps/pthread/tst-exec1.c Normal file
View File

@ -0,0 +1,156 @@
/* Simple exec test, only a thread in the parent.
Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <paths.h>
#include <pthread.h>
#include <signal.h>
#include <spawn.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <support/xsignal.h>
static void *
tf (void *arg)
{
pthread_t th = (pthread_t) arg;
if (pthread_join (th, NULL) == 0)
{
puts ("thread in parent joined!?");
exit (1);
}
puts ("join in thread in parent returned!?");
exit (1);
}
static int
do_test (void)
{
int fd[2];
if (pipe (fd) != 0)
{
puts ("pipe failed");
exit (1);
}
/* Not interested in knowing when the pipe is closed. */
xsignal (SIGPIPE, SIG_IGN);
posix_spawn_file_actions_t a;
if (posix_spawn_file_actions_init (&a) != 0)
{
puts ("spawn_file_actions_init failed");
exit (1);
}
if (posix_spawn_file_actions_adddup2 (&a, fd[1], STDOUT_FILENO) != 0)
{
puts ("spawn_file_actions_adddup2 failed");
exit (1);
}
if (posix_spawn_file_actions_addclose (&a, fd[0]) != 0)
{
puts ("spawn_file_actions_addclose");
exit (1);
}
pthread_t th;
if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
{
puts ("create failed");
exit (1);
}
pid_t pid;
char *argv[] = { (char *) _PATH_BSHELL, (char *) "-c", (char *) "echo $$",
NULL };
if (posix_spawn (&pid, _PATH_BSHELL, &a, NULL, argv, NULL) != 0)
{
puts ("spawn failed");
exit (1);
}
close (fd[1]);
char buf[200];
ssize_t n;
bool seen_pid = false;
while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
{
/* We only expect to read the PID. */
char *endp;
long int rpid = strtol (buf, &endp, 10);
if (*endp != '\n')
{
printf ("didn't parse whole line: \"%s\"\n", buf);
exit (1);
}
if (endp == buf)
{
puts ("read empty line");
exit (1);
}
if (rpid != pid)
{
printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
exit (1);
}
if (seen_pid)
{
puts ("found more than one PID line");
exit (1);
}
seen_pid = true;
}
close (fd[0]);
int status;
int err = waitpid (pid, &status, 0);
if (err != pid)
{
puts ("waitpid failed");
exit (1);
}
if (!seen_pid)
{
puts ("didn't get PID");
exit (1);
}
puts ("read correct PID");
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

151
sysdeps/pthread/tst-exec2.c Normal file
View File

@ -0,0 +1,151 @@
/* Thread with running thread calls exec.
Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <paths.h>
#include <pthread.h>
#include <signal.h>
#include <spawn.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <support/xsignal.h>
static void *
tf (void *arg)
{
pthread_t th = (pthread_t) arg;
if (pthread_join (th, NULL) == 0)
{
puts ("thread in parent joined!?");
exit (1);
}
puts ("join in thread in parent returned!?");
exit (1);
}
static int
do_test (void)
{
int fd[2];
if (pipe (fd) != 0)
{
puts ("pipe failed");
exit (1);
}
/* Not interested in knowing when the pipe is closed. */
xsignal (SIGPIPE, SIG_IGN);
pid_t pid = fork ();
if (pid == -1)
{
puts ("fork failed");
exit (1);
}
if (pid == 0)
{
/* Use the fd for stdout. This is kind of ugly because it
substitutes the fd of stdout but we know what we are doing
here... */
if (dup2 (fd[1], STDOUT_FILENO) != STDOUT_FILENO)
{
puts ("dup2 failed");
exit (1);
}
close (fd[0]);
pthread_t th;
if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
{
puts ("create failed");
exit (1);
}
execl (_PATH_BSHELL, _PATH_BSHELL, "-c", "echo $$", NULL);
puts ("execl failed");
exit (1);
}
close (fd[1]);
char buf[200];
ssize_t n;
bool seen_pid = false;
while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
{
/* We only expect to read the PID. */
char *endp;
long int rpid = strtol (buf, &endp, 10);
if (*endp != '\n')
{
printf ("didn't parse whole line: \"%s\"\n", buf);
exit (1);
}
if (endp == buf)
{
puts ("read empty line");
exit (1);
}
if (rpid != pid)
{
printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
exit (1);
}
if (seen_pid)
{
puts ("found more than one PID line");
exit (1);
}
seen_pid = true;
}
close (fd[0]);
int status;
int err = waitpid (pid, &status, 0);
if (err != pid)
{
puts ("waitpid failed");
exit (1);
}
if (!seen_pid)
{
puts ("didn't get PID");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

149
sysdeps/pthread/tst-exec3.c Normal file
View File

@ -0,0 +1,149 @@
/* Thread calls exec.
Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <paths.h>
#include <pthread.h>
#include <signal.h>
#include <spawn.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <support/xsignal.h>
static void *
tf (void *arg)
{
execl (_PATH_BSHELL, _PATH_BSHELL, "-c", "echo $$", NULL);
puts ("execl failed");
exit (1);
}
static int
do_test (void)
{
int fd[2];
if (pipe (fd) != 0)
{
puts ("pipe failed");
exit (1);
}
/* Not interested in knowing when the pipe is closed. */
xsignal (SIGPIPE, SIG_IGN);
pid_t pid = fork ();
if (pid == -1)
{
puts ("fork failed");
exit (1);
}
if (pid == 0)
{
/* Use the fd for stdout. This is kind of ugly because it
substitutes the fd of stdout but we know what we are doing
here... */
if (dup2 (fd[1], STDOUT_FILENO) != STDOUT_FILENO)
{
puts ("dup2 failed");
exit (1);
}
close (fd[0]);
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
exit (1);
}
if (pthread_join (th, NULL) == 0)
{
puts ("join succeeded!?");
exit (1);
}
puts ("join returned!?");
exit (1);
}
close (fd[1]);
char buf[200];
ssize_t n;
bool seen_pid = false;
while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
{
/* We only expect to read the PID. */
char *endp;
long int rpid = strtol (buf, &endp, 10);
if (*endp != '\n')
{
printf ("didn't parse whole line: \"%s\"\n", buf);
exit (1);
}
if (endp == buf)
{
puts ("read empty line");
exit (1);
}
if (rpid != pid)
{
printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
exit (1);
}
if (seen_pid)
{
puts ("found more than one PID line");
exit (1);
}
seen_pid = true;
}
close (fd[0]);
int status;
int err = waitpid (pid, &status, 0);
if (err != pid)
{
puts ("waitpid failed");
exit (1);
}
if (!seen_pid)
{
puts ("didn't get PID");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,78 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
/* NOTE: this tests functionality beyond POSIX. POSIX does not allow
exit to be called more than once. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
static pthread_barrier_t b;
static void *
tf (void *arg)
{
int r = pthread_barrier_wait (&b);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
exit (0);
}
static int
do_test (void)
{
if (pthread_barrier_init (&b, NULL, 2) != 0)
{
puts ("barrier_init failed");
exit (1);
}
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
exit (1);
}
int r = pthread_barrier_wait (&b);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
/* Do nothing. */
if (pthread_join (th, NULL) == 0)
{
puts ("join succeeded!?");
exit (1);
}
puts ("join returned!?");
exit (1);
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,42 @@
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static int do_test (void);
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
static void *
tf (void *arg)
{
while (1)
sleep (100);
/* NOTREACHED */
return NULL;
}
static int
do_test (void)
{
pthread_t th;
int e = pthread_create (&th, NULL, tf, NULL);
if (e != 0)
{
printf ("create failed: %s\n", strerror (e));
return 1;
}
delayed_exit (1);
/* Terminate only this thread. */
pthread_exit (NULL);
/* NOTREACHED */
return 1;
}

View File

@ -0,0 +1,83 @@
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int do_test (void);
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
static pthread_barrier_t b;
static void *
tf2 (void *arg)
{
while (1)
sleep (100);
/* NOTREACHED */
return NULL;
}
static void *
tf (void *arg)
{
pthread_t th;
int e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
e = pthread_create (&th, NULL, tf2, NULL);
if (e != 0)
{
printf ("create failed: %s\n", strerror (e));
exit (1);
}
/* Terminate only this thread. */
return NULL;
}
static int
do_test (void)
{
pthread_t th;
if (pthread_barrier_init (&b, NULL, 2) != 0)
{
puts ("barrier_init failed");
exit (1);
}
int e = pthread_create (&th, NULL, tf, NULL);
if (e != 0)
{
printf ("create failed: %s\n", strerror (e));
exit (1);
}
e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
delayed_exit (3);
/* Terminate only this thread. */
pthread_exit (NULL);
/* NOTREACHED */
return 1;
}

View File

@ -0,0 +1,92 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/file.h>
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static int fd;
static void *
tf (void *arg)
{
if (flock (fd, LOCK_SH | LOCK_NB) != 0)
{
puts ("second flock failed");
exit (1);
}
pthread_mutex_unlock (&lock);
return NULL;
}
static int
do_test (void)
{
char tmp[] = "/tmp/tst-flock1-XXXXXX";
fd = mkstemp (tmp);
if (fd == -1)
{
puts ("mkstemp failed");
exit (1);
}
unlink (tmp);
write (fd, "foobar xyzzy", 12);
if (flock (fd, LOCK_EX | LOCK_NB) != 0)
{
puts ("first flock failed");
exit (1);
}
pthread_mutex_lock (&lock);
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("pthread_create failed");
exit (1);
}
pthread_mutex_lock (&lock);
void *result;
if (pthread_join (th, &result) != 0)
{
puts ("pthread_join failed");
exit (1);
}
close (fd);
return result != NULL;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

121
sysdeps/pthread/tst-fork1.c Normal file
View File

@ -0,0 +1,121 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Roland McGrath <roland@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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
static void *
thread_function (void * arg)
{
int i = (intptr_t) arg;
int status;
pid_t pid;
pid_t pid2;
pid = fork ();
switch (pid)
{
case 0:
printf ("%ld for %d\n", (long int) getpid (), i);
struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 * i };
nanosleep (&ts, NULL);
_exit (i);
break;
case -1:
printf ("fork: %m\n");
return (void *) 1l;
break;
}
pid2 = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
if (pid2 != pid)
{
printf ("waitpid returned %ld, expected %ld\n",
(long int) pid2, (long int) pid);
return (void *) 1l;
}
printf ("%ld with %d, expected %d\n",
(long int) pid, WEXITSTATUS (status), i);
return WEXITSTATUS (status) == i ? NULL : (void *) 1l;
}
#define N 5
static const int t[N] = { 7, 6, 5, 4, 3 };
static int
do_test (void)
{
pthread_t th[N];
int i;
int result = 0;
pthread_attr_t at;
if (pthread_attr_init (&at) != 0)
{
puts ("attr_init failed");
return 1;
}
if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
{
puts ("attr_setstacksize failed");
return 1;
}
for (i = 0; i < N; ++i)
if (pthread_create (&th[i], NULL, thread_function,
(void *) (intptr_t) t[i]) != 0)
{
printf ("creation of thread %d failed\n", i);
exit (1);
}
if (pthread_attr_destroy (&at) != 0)
{
puts ("attr_destroy failed");
return 1;
}
for (i = 0; i < N; ++i)
{
void *v;
if (pthread_join (th[i], &v) != 0)
{
printf ("join of thread %d failed\n", i);
result = 1;
}
else if (v != NULL)
{
printf ("join %d successful, but child failed\n", i);
result = 1;
}
else
printf ("join %d successful\n", i);
}
return result;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,89 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Roland McGrath <roland@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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
static pid_t initial_pid;
static void *
tf (void *arg)
{
if (getppid () != initial_pid)
{
printf ("getppid in thread returned %ld, expected %ld\n",
(long int) getppid (), (long int) initial_pid);
return (void *) -1;
}
return NULL;
}
int
main (void)
{
initial_pid = getpid ();
pid_t child = fork ();
if (child == 0)
{
if (getppid () != initial_pid)
{
printf ("first getppid returned %ld, expected %ld\n",
(long int) getppid (), (long int) initial_pid);
exit (1);
}
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("pthread_create failed");
exit (1);
}
void *result;
if (pthread_join (th, &result) != 0)
{
puts ("pthread_join failed");
exit (1);
}
exit (result == NULL ? 0 : 1);
}
else if (child == -1)
{
puts ("initial fork failed");
return 1;
}
int status;
if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
{
printf ("waitpid failed: %m\n");
return 1;
}
return status;
}

108
sysdeps/pthread/tst-fork3.c Normal file
View File

@ -0,0 +1,108 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Roland McGrath <roland@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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
static pid_t initial_pid;
static void *
tf2 (void *arg)
{
if (getppid () != initial_pid)
{
printf ("getppid in thread returned %ld, expected %ld\n",
(long int) getppid (), (long int) initial_pid);
return (void *) -1;
}
return NULL;
}
static void *
tf1 (void *arg)
{
pid_t child = fork ();
if (child == 0)
{
if (getppid () != initial_pid)
{
printf ("first getppid returned %ld, expected %ld\n",
(long int) getppid (), (long int) initial_pid);
exit (1);
}
pthread_t th2;
if (pthread_create (&th2, NULL, tf2, NULL) != 0)
{
puts ("child: pthread_create failed");
exit (1);
}
void *result;
if (pthread_join (th2, &result) != 0)
{
puts ("pthread_join failed");
exit (1);
}
exit (result == NULL ? 0 : 1);
}
else if (child == -1)
{
puts ("initial fork failed");
exit (1);
}
int status;
if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
{
printf ("waitpid failed: %m\n");
exit (1);
}
exit (status);
}
static int
do_test (void)
{
initial_pid = getpid ();
pthread_t th1;
if (pthread_create (&th1, NULL, tf1, NULL) != 0)
{
puts ("parent: pthread_create failed");
exit (1);
}
/* This call should never return. */
pthread_join (th1, NULL);
return 1;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,64 @@
/* Test of fork updating child universe's pthread structures.
Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
static int
do_test (void)
{
pthread_t me = pthread_self ();
pid_t pid = fork ();
if (pid < 0)
{
printf ("fork: %m\n");
return 1;
}
if (pid == 0)
{
int err = pthread_kill (me, SIGTERM);
printf ("pthread_kill returned: %s\n", strerror (err));
return 3;
}
int status;
errno = 0;
if (wait (&status) != pid)
printf ("wait failed: %m\n");
else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGTERM)
{
printf ("child correctly died with SIGTERM\n");
return 0;
}
else
printf ("child died with bad status %#x\n", status);
return 1;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,114 @@
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
static pid_t pid;
static void *
pid_thread (void *arg)
{
if (pid != getpid ())
{
printf ("pid wrong in thread: should be %d, is %d\n",
(int) pid, (int) getpid ());
return (void *) 1L;
}
return NULL;
}
static int
do_test (void)
{
pid = getpid ();
pthread_t thr;
int ret = pthread_create (&thr, NULL, pid_thread, NULL);
if (ret)
{
printf ("pthread_create failed: %d\n", ret);
return 1;
}
void *thr_ret;
ret = pthread_join (thr, &thr_ret);
if (ret)
{
printf ("pthread_create failed: %d\n", ret);
return 1;
}
else if (thr_ret)
{
printf ("thread getpid failed\n");
return 1;
}
pid_t child = fork ();
if (child == -1)
{
printf ("fork failed: %m\n");
return 1;
}
else if (child == 0)
{
if (pid == getpid ())
{
puts ("pid did not change after fork");
exit (1);
}
pid = getpid ();
ret = pthread_create (&thr, NULL, pid_thread, NULL);
if (ret)
{
printf ("pthread_create failed: %d\n", ret);
return 1;
}
ret = pthread_join (thr, &thr_ret);
if (ret)
{
printf ("pthread_create failed: %d\n", ret);
return 1;
}
else if (thr_ret)
{
printf ("thread getpid failed\n");
return 1;
}
return 0;
}
int status;
if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
{
puts ("waitpid failed");
kill (child, SIGKILL);
return 1;
}
if (!WIFEXITED (status))
{
if (WIFSIGNALED (status))
printf ("died from signal %s\n", strsignal (WTERMSIG (status)));
else
puts ("did not terminate correctly");
return 1;
}
if (WEXITSTATUS (status) != 0)
{
printf ("exit code %d\n", WEXITSTATUS (status));
return 1;
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,99 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
static pthread_barrier_t b;
static void *
tf (void *a)
{
if (pthread_mutex_lock (&m) != 0)
{
puts ("child: mutex_lock failed");
exit (1);
}
int e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("child: barrier_wait failed");
exit (1);
}
/* This call should never return. */
pthread_cond_wait (&c, &m);
return NULL;
}
int
do_test (void)
{
pthread_t th;
if (pthread_barrier_init (&b, NULL, 2) != 0)
{
puts ("barrier_init failed");
exit (1);
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
exit (1);
}
int e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
if (pthread_mutex_lock (&m) != 0)
{
puts ("mutex_lock failed");
exit (1);
}
/* Send the thread a signal which it doesn't catch and which will
cause the process to terminate. */
if (pthread_kill (th, SIGUSR1) != 0)
{
puts ("kill failed");
exit (1);
}
/* This call should never return. */
pthread_join (th, NULL);
return 0;
}
#define EXPECTED_SIGNAL SIGUSR1
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

137
sysdeps/pthread/tst-kill2.c Normal file
View File

@ -0,0 +1,137 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
static pthread_barrier_t b;
static void *
tf (void *a)
{
/* Block SIGUSR1. */
sigset_t ss;
sigemptyset (&ss);
sigaddset (&ss, SIGUSR1);
if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
{
puts ("child: sigmask failed");
exit (1);
}
if (pthread_mutex_lock (&m) != 0)
{
puts ("child: mutex_lock failed");
exit (1);
}
int e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("child: barrier_wait failed");
exit (1);
}
/* Compute timeout. */
struct timeval tv;
(void) gettimeofday (&tv, NULL);
struct timespec ts;
TIMEVAL_TO_TIMESPEC (&tv, &ts);
/* Timeout: 1sec. */
ts.tv_sec += 1;
/* This call should never return. */
if (pthread_cond_timedwait (&c, &m, &ts) != ETIMEDOUT)
{
puts ("cond_timedwait didn't time out");
exit (1);
}
return NULL;
}
int
do_test (void)
{
pthread_t th;
if (pthread_barrier_init (&b, NULL, 2) != 0)
{
puts ("barrier_init failed");
exit (1);
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
exit (1);
}
int e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
if (pthread_mutex_lock (&m) != 0)
{
puts ("mutex_lock failed");
exit (1);
}
/* Send the thread a signal which it has blocked. */
if (pthread_kill (th, SIGUSR1) != 0)
{
puts ("kill failed");
exit (1);
}
if (pthread_mutex_unlock (&m) != 0)
{
puts ("mutex_unlock failed");
exit (1);
}
void *r;
if (pthread_join (th, &r) != 0)
{
puts ("join failed");
exit (1);
}
if (r != NULL)
{
puts ("return value wrong");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

158
sysdeps/pthread/tst-kill3.c Normal file
View File

@ -0,0 +1,158 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
static int do_test (void);
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
static pthread_barrier_t b;
static void
handler (int sig)
{
write_message ("handler called\n");
_exit (1);
}
static void *
tf (void *a)
{
/* Block SIGUSR1. */
sigset_t ss;
sigemptyset (&ss);
sigaddset (&ss, SIGUSR1);
if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
{
puts ("child: sigmask failed");
exit (1);
}
if (pthread_mutex_lock (&m) != 0)
{
puts ("child: mutex_lock failed");
exit (1);
}
int e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("child: barrier_wait failed");
exit (1);
}
/* Compute timeout. */
struct timeval tv;
(void) gettimeofday (&tv, NULL);
struct timespec ts;
TIMEVAL_TO_TIMESPEC (&tv, &ts);
/* Timeout: 1sec. */
ts.tv_sec += 1;
/* This call should never return. */
if (pthread_cond_timedwait (&c, &m, &ts) != ETIMEDOUT)
{
puts ("cond_timedwait didn't time out");
exit (1);
}
return NULL;
}
int
do_test (void)
{
pthread_t th;
struct sigaction sa;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = handler;
if (sigaction (SIGUSR1, &sa, NULL) != 0)
{
puts ("sigaction failed");
exit (1);
}
if (pthread_barrier_init (&b, NULL, 2) != 0)
{
puts ("barrier_init failed");
exit (1);
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
exit (1);
}
int e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
if (pthread_mutex_lock (&m) != 0)
{
puts ("mutex_lock failed");
exit (1);
}
/* Send the thread a signal which it has blocked. */
if (pthread_kill (th, SIGUSR1) != 0)
{
puts ("kill failed");
exit (1);
}
if (pthread_mutex_unlock (&m) != 0)
{
puts ("mutex_unlock failed");
exit (1);
}
void *r;
if (pthread_join (th, &r) != 0)
{
puts ("join failed");
exit (1);
}
if (r != NULL)
{
puts ("return value wrong");
exit (1);
}
return 0;
}

View File

@ -0,0 +1,90 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static void *
tf (void *a)
{
return NULL;
}
int
do_test (void)
{
pthread_attr_t at;
if (pthread_attr_init (&at) != 0)
{
puts ("attr_create failed");
exit (1);
}
/* Limit thread stack size, because if it is too large, pthread_join
will free it immediately rather than put it into stack cache. */
if (pthread_attr_setstacksize (&at, 2 * 1024 * 1024) != 0)
{
puts ("setstacksize failed");
exit (1);
}
pthread_t th;
if (pthread_create (&th, &at, tf, NULL) != 0)
{
puts ("create failed");
exit (1);
}
pthread_attr_destroy (&at);
if (pthread_join (th, NULL) != 0)
{
puts ("join failed");
exit (1);
}
/* The following only works because we assume here something about
the implementation. Namely, that the memory allocated for the
thread descriptor is not going away, that the TID field is
cleared and therefore the signal is sent to process 0, and that
we can savely assume there is no other process with this ID at
that time. */
int e = pthread_kill (th, 0);
if (e == 0)
{
puts ("pthread_kill succeeded");
exit (1);
}
if (e != ESRCH)
{
puts ("pthread_kill didn't return ESRCH");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,49 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
int
do_test (void)
{
/* XXX This test might require architecture and system specific changes.
There is no guarantee that this signal number is invalid. */
int e = pthread_kill (pthread_self (), INT_MAX);
if (e == 0)
{
puts ("kill didn't failed");
exit (1);
}
if (e != EINVAL)
{
puts ("error not EINVAL");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

162
sysdeps/pthread/tst-kill6.c Normal file
View File

@ -0,0 +1,162 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int do_test (void);
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
static pthread_t receiver;
static sem_t sem;
static pthread_barrier_t b;
static void
handler (int sig)
{
if (sig != SIGUSR1)
{
write_message ("wrong signal\n");
_exit (1);
}
if (pthread_self () != receiver)
{
write_message ("not the intended receiver\n");
_exit (1);
}
if (sem_post (&sem) != 0)
{
write_message ("sem_post failed\n");
_exit (1);
}
}
static void *
tf (void *a)
{
int e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("child: barrier_wait failed");
exit (1);
}
return NULL;
}
int
do_test (void)
{
struct sigaction sa;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = handler;
if (sigaction (SIGUSR1, &sa, NULL) != 0)
{
puts ("sigaction failed");
exit (1);
}
#define N 20
if (pthread_barrier_init (&b, NULL, N + 1) != 0)
{
puts ("barrier_init failed");
exit (1);
}
pthread_attr_t a;
if (pthread_attr_init (&a) != 0)
{
puts ("attr_init failed");
exit (1);
}
if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
{
puts ("attr_setstacksize failed");
return 1;
}
pthread_t th[N];
int i;
for (i = 0; i < N; ++i)
if (pthread_create (&th[i], &a, tf, NULL) != 0)
{
puts ("create failed");
exit (1);
}
if (pthread_attr_destroy (&a) != 0)
{
puts ("attr_destroy failed");
exit (1);
}
if (sem_init (&sem, 0, 0) != 0)
{
puts ("sem_init failed");
exit (1);
}
for (i = 0; i < N * 10; ++i)
{
receiver = th[i % N];
if (pthread_kill (receiver, SIGUSR1) != 0)
{
puts ("kill failed");
exit (1);
}
if (TEMP_FAILURE_RETRY (sem_wait (&sem)) != 0)
{
puts ("sem_wait failed");
exit (1);
}
}
int e = pthread_barrier_wait (&b);
if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("barrier_wait failed");
exit (1);
}
for (i = 0; i < N; ++i)
if (pthread_join (th[i], NULL) != 0)
{
puts ("join failed");
exit (1);
}
return 0;
}

View File

@ -0,0 +1,22 @@
/* Test that the thread-local locale works right in the main thread
when statically linked. */
#include "../locale/tst-C-locale.c"
#include <pthread.h>
#include <signal.h>
/* This is never called, just here to get pthreads linked in. */
int
useless (void)
{
pthread_t th;
pthread_create (&th, 0, (void *(*) (void *)) useless, 0);
int result = 0;
#ifdef SIGRTMIN
/* This is to check __libc_current_sigrt* can be used in statically
linked apps. */
result = SIGRTMIN;
#endif
return result;
}

View File

@ -0,0 +1,15 @@
/* Test that the thread-local locale works right in the main thread
when statically linked. */
#include "../argp/tst-argp1.c"
#include <pthread.h>
/* This is never called, just here to get pthreads linked in. */
void *
useless (void *a)
{
pthread_t th;
pthread_create (&th, 0, useless, a);
return NULL;
}

View File

@ -0,0 +1,101 @@
/* Test for open_memstream locking.
Copyright (C) 2017-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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
<https://www.gnu.org/licenses/>. */
/* This test checks if concurrent writes to a FILE created with
open_memstream are correctly interleaved without loss or corruption
of data. Large number of concurrent fputc operations are used
and in the end the bytes written to the memstream buffer are
counted to see if they all got recorded.
This is a regression test to see if the single threaded stdio
optimization broke multi-threaded open_memstream usage. */
#include <pthread.h>
#include <stdio.h>
#include <support/check.h>
#include <support/xthread.h>
enum
{
thread_count = 2,
byte_count = 1000000,
};
struct closure
{
FILE *fp;
char b;
};
static void *
thread_func (void *closure)
{
struct closure *args = closure;
for (int i = 0; i < byte_count; ++i)
fputc (args->b, args->fp);
return NULL;
}
int
do_test (void)
{
char *buffer = NULL;
size_t buffer_length = 0;
FILE *fp = open_memstream (&buffer, &buffer_length);
if (fp == NULL)
FAIL_RET ("open_memstream: %m");
pthread_t threads[thread_count];
struct closure args[thread_count];
for (int i = 0; i < thread_count; ++i)
{
args[i].fp = fp;
args[i].b = 'A' + i;
threads[i] = xpthread_create (NULL, thread_func, args + i);
}
for (int i = 0; i < thread_count; ++i)
xpthread_join (threads[i]);
fclose (fp);
if (buffer_length != thread_count * byte_count)
FAIL_RET ("unexpected number of written bytes: %zu (should be %d)",
buffer_length, thread_count * byte_count);
/* Verify that each thread written its unique character byte_count times. */
size_t counts[thread_count] = { 0, };
for (size_t i = 0; i < buffer_length; ++i)
{
if (buffer[i] < 'A' || buffer[i] >= 'A' + thread_count)
FAIL_RET ("written byte at %zu out of range: %d", i, buffer[i] & 0xFF);
++counts[buffer[i] - 'A'];
}
for (int i = 0; i < thread_count; ++i)
if (counts[i] != byte_count)
FAIL_RET ("incorrect write count for thread %d: %zu (should be %d)", i,
counts[i], byte_count);
return 0;
}
#define TIMEOUT 100
#include <support/test-driver.c>

View File

@ -0,0 +1,70 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <tst-stack-align.h>
static void *
tf (void *arg)
{
bool ok = true;
puts ("in thread");
if (TEST_STACK_ALIGN ())
ok = false;
return ok ? NULL : (void *) -1l;
}
static int
do_test (void)
{
bool ok = true;
puts ("in main");
if (TEST_STACK_ALIGN ())
ok = false;
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
return 1;
}
void *res;
if (pthread_join (th, &res) != 0)
{
puts ("join failed");
return 1;
}
if (res != NULL)
ok = false;
return ok ? 0 : 1;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,56 @@
/* Copyright (C) 2005-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2005.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <tst-stack-align.h>
static bool ok = true;
static pthread_once_t once = PTHREAD_ONCE_INIT;
static void
once_test (void)
{
puts ("in once_test");
if (TEST_STACK_ALIGN ())
ok = false;
}
static int
do_test (void)
{
puts ("in main");
if (TEST_STACK_ALIGN ())
ok = false;
if (pthread_once (&once, once_test))
{
puts ("pthread once failed");
return 1;
}
return ok ? 0 : 1;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,59 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <error.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static void *
dummy (void *x)
{
return NULL;
}
static char buf[sizeof "something\n"];
static int
do_test (void)
{
FILE *f;
pthread_t p;
int err;
f = popen ("echo something", "r");
if (f == NULL)
error (EXIT_FAILURE, errno, "popen failed");
if (fgets (buf, sizeof (buf), f) == NULL)
error (EXIT_FAILURE, 0, "fgets failed");
if (strcmp (buf, "something\n"))
error (EXIT_FAILURE, 0, "read wrong data");
if (pclose (f))
error (EXIT_FAILURE, errno, "pclose returned non-zero");
if ((err = pthread_create (&p, NULL, dummy, NULL)))
error (EXIT_FAILURE, err, "pthread_create failed");
if ((err = pthread_join (p, NULL)))
error (EXIT_FAILURE, err, "pthread_join failed");
exit (0);
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,47 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
static int
do_test (void)
{
puts ("We expect no limits");
/* We have no fixed limit on the number of threads. Make sure the
headers tell the right story. */
#ifdef PTHREAD_THREADS_MAX
printf ("Header report maximum number of threads = %lu\n",
(unsigned long int) PTHREAD_THREADS_MAX);
return 1;
#else
long int r = sysconf (_SC_THREAD_THREADS_MAX);
if (r != -1)
{
printf ("sysconf(_SC_THREAD_THREADS_MAX) return %ld\n", r);
return 1;
}
#endif
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,119 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <support/support.h>
#include <support/check.h>
#include <support/xthread.h>
struct test_s
{
__attribute__ ((aligned(0x20))) int a;
__attribute__ ((aligned(0x200))) int b;
};
#define INIT_A 1
#define INIT_B 42
/* Deliberately not static. */
__thread struct test_s s __attribute__ ((tls_model ("initial-exec"))) =
{
.a = INIT_A,
.b = INIT_B
};
/* Use noinline in combination with not static to ensure that the
alignment check is really done. Otherwise it was optimized out! */
__attribute__ ((noinline)) void
check_alignment (const char *thr_name, const char *ptr_name,
int *ptr, int alignment)
{
uintptr_t offset_aligment = ((uintptr_t) ptr) & (alignment - 1);
if (offset_aligment)
{
FAIL_EXIT1 ("%s (%p) is not 0x%x-byte aligned in %s thread\n",
ptr_name, ptr, alignment, thr_name);
}
}
static void
check_s (const char *thr_name)
{
if (s.a != INIT_A || s.b != INIT_B)
FAIL_EXIT1 ("initial value of s in %s thread wrong\n", thr_name);
check_alignment (thr_name, "s.a", &s.a, 0x20);
check_alignment (thr_name, "s.b", &s.b, 0x200);
}
static void *
tf (void *arg)
{
check_s ("child");
++s.a;
return NULL;
}
int
do_test (void)
{
check_s ("main");
pthread_attr_t a;
xpthread_attr_init (&a);
#define STACK_SIZE (1 * 1024 * 1024)
xpthread_attr_setstacksize (&a, STACK_SIZE);
#define N 10
int i;
for (i = 0; i < N; ++i)
{
#define M 10
pthread_t th[M];
int j;
for (j = 0; j < M; ++j, ++s.a)
th[j] = xpthread_create (&a, tf, NULL);
for (j = 0; j < M; ++j)
xpthread_join (th[j]);
}
/* Also check the alignment of the tls variables if a misaligned stack is
specified. */
pthread_t th;
void *thr_stack = NULL;
thr_stack = xposix_memalign (0x200, STACK_SIZE + 1);
xpthread_attr_setstack (&a, thr_stack + 1, STACK_SIZE);
th = xpthread_create (&a, tf, NULL);
xpthread_join (th);
free (thr_stack);
xpthread_attr_destroy (&a);
return 0;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,206 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define N 10
static pthread_t th[N];
static int do_test (void);
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
#define CB(n) \
static void \
cb##n (void) \
{ \
if (th[n] != pthread_self ()) \
{ \
write_message ("wrong callback\n"); \
_exit (1); \
} \
}
CB (0)
CB (1)
CB (2)
CB (3)
CB (4)
CB (5)
CB (6)
CB (7)
CB (8)
CB (9)
static void (*cbs[]) (void) =
{
cb0, cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9
};
static __thread void (*fp) (void) __attribute__ ((tls_model ("local-exec")));
static sem_t s;
#define THE_SIG SIGUSR1
static void
handler (int sig)
{
if (sig != THE_SIG)
{
write_message ("wrong signal\n");
_exit (1);
}
fp ();
if (sem_post (&s) != 0)
{
write_message ("sem_post failed\n");
_exit (1);
}
}
static pthread_barrier_t b;
#define TOTAL_SIGS 1000
static int nsigs;
static void *
tf (void *arg)
{
fp = arg;
pthread_barrier_wait (&b);
pthread_barrier_wait (&b);
if (nsigs != TOTAL_SIGS)
{
puts ("barrier_wait prematurely returns");
exit (1);
}
return NULL;
}
int
do_test (void)
{
if (pthread_barrier_init (&b, NULL, N + 1) != 0)
{
puts ("barrier_init failed");
exit (1);
}
if (sem_init (&s, 0, 0) != 0)
{
puts ("sem_init failed");
exit (1);
}
struct sigaction sa;
sa.sa_handler = handler;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction (THE_SIG, &sa, NULL) != 0)
{
puts ("sigaction failed");
exit (1);
}
pthread_attr_t a;
if (pthread_attr_init (&a) != 0)
{
puts ("attr_init failed");
exit (1);
}
if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
{
puts ("attr_setstacksize failed");
return 1;
}
int i;
for (i = 0; i < N; ++i)
if (pthread_create (&th[i], &a, tf, cbs[i]) != 0)
{
puts ("pthread_create failed");
exit (1);
}
if (pthread_attr_destroy (&a) != 0)
{
puts ("attr_destroy failed");
exit (1);
}
pthread_barrier_wait (&b);
sigset_t ss;
sigemptyset (&ss);
sigaddset (&ss, THE_SIG);
if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
{
puts ("pthread_sigmask failed");
exit (1);
}
/* Start sending signals. */
for (i = 0; i < TOTAL_SIGS; ++i)
{
if (kill (getpid (), THE_SIG) != 0)
{
puts ("kill failed");
exit (1);
}
if (TEMP_FAILURE_RETRY (sem_wait (&s)) != 0)
{
puts ("sem_wait failed");
exit (1);
}
++nsigs;
}
pthread_barrier_wait (&b);
for (i = 0; i < N; ++i)
if (pthread_join (th[i], NULL) != 0)
{
puts ("join failed");
exit (1);
}
return 0;
}

View File

@ -0,0 +1 @@
#include <posix/tst-vfork1.c>

View File

@ -0,0 +1 @@
#include <posix/tst-vfork2.c>

View File

@ -0,0 +1,61 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <error.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
volatile int count;
void
sh (int sig)
{
++count;
}
int
main (void)
{
struct sigaction sa;
sa.sa_handler = sh;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction (SIGUSR1, &sa, NULL) < 0)
{
printf ("sigaction failed: %m\n");
exit (1);
}
if (raise (SIGUSR1) < 0)
{
printf ("first raise failed: %m\n");
exit (1);
}
if (raise (SIGUSR1) < 0)
{
printf ("second raise failed: %m\n");
exit (1);
}
if (count != 2)
{
printf ("signal handler not called 2 times\n");
exit (1);
}
exit (0);
}

View File

@ -0,0 +1,118 @@
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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
<https://www.gnu.org/licenses/>. */
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <stdbool.h>
#include <unistd.h>
/* The test must run under a non-privileged user ID. */
static const uid_t test_uid = 1;
static pthread_barrier_t barrier1;
static pthread_barrier_t barrier2;
#define FAIL(fmt, ...) \
do { printf ("FAIL: " fmt "\n", __VA_ARGS__); _exit (1); } while (0)
#define FAIL_ERR(fmt, ...) \
do { printf ("FAIL: " fmt ": %m\n", __VA_ARGS__); _exit (1); } while (0)
/* True if x is not a successful return code from pthread_barrier_wait. */
static inline bool
is_invalid_barrier_ret (int x)
{
return x != 0 && x != PTHREAD_BARRIER_SERIAL_THREAD;
}
static void *
thread_func (void *ctx __attribute__ ((unused)))
{
int ret = pthread_barrier_wait (&barrier1);
if (is_invalid_barrier_ret (ret))
FAIL ("pthread_barrier_wait (barrier1) (on thread): %d", ret);
ret = pthread_barrier_wait (&barrier2);
if (is_invalid_barrier_ret (ret))
FAIL ("pthread_barrier_wait (barrier2) (on thread): %d", ret);
return NULL;
}
static void
setuid_failure (int phase)
{
int ret = setuid (0);
switch (ret)
{
case 0:
FAIL ("setuid succeeded unexpectedly in phase %d", phase);
case -1:
if (errno != EPERM)
FAIL_ERR ("setuid phase %d", phase);
break;
default:
FAIL ("invalid setuid return value in phase %d: %d", phase, ret);
}
}
static int
do_test (void)
{
if (getuid () == 0)
if (setuid (test_uid) != 0)
FAIL_ERR ("setuid (%u)", (unsigned) test_uid);
if (setuid (getuid ()))
FAIL_ERR ("setuid (%s)", "getuid ()");
setuid_failure (1);
int ret = pthread_barrier_init (&barrier1, NULL, 2);
if (ret != 0)
FAIL ("pthread_barrier_init (barrier1): %d", ret);
ret = pthread_barrier_init (&barrier2, NULL, 2);
if (ret != 0)
FAIL ("pthread_barrier_init (barrier2): %d", ret);
pthread_t thread;
ret = pthread_create (&thread, NULL, thread_func, NULL);
if (ret != 0)
FAIL ("pthread_create: %d", ret);
/* Ensure that the thread is running properly. */
ret = pthread_barrier_wait (&barrier1);
if (is_invalid_barrier_ret (ret))
FAIL ("pthread_barrier_wait (barrier1): %d", ret);
setuid_failure (2);
/* Check success case. */
if (setuid (getuid ()) != 0)
FAIL_ERR ("setuid (%s)", "getuid ()");
/* Shutdown. */
ret = pthread_barrier_wait (&barrier2);
if (is_invalid_barrier_ret (ret))
FAIL ("pthread_barrier_wait (barrier2): %d", ret);
ret = pthread_join (thread, NULL);
if (ret != 0)
FAIL ("pthread_join: %d", ret);
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,59 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
static int
do_test (void)
{
sigset_t ss;
sigemptyset (&ss);
int i;
for (i = 0; i < 10000; ++i)
{
long int r = random ();
if (r != SIG_BLOCK && r != SIG_SETMASK && r != SIG_UNBLOCK)
{
int e = pthread_sigmask (r, &ss, NULL);
if (e == 0)
{
printf ("pthread_sigmask succeeded for how = %ld\n", r);
exit (1);
}
if (e != EINVAL)
{
puts ("pthread_sigmask didn't return EINVAL");
exit (1);
}
}
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,110 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
static sigset_t ss;
static void *
tf (void *arg)
{
sigset_t ss2;
if (pthread_sigmask (SIG_SETMASK, NULL, &ss2) != 0)
{
puts ("child: sigmask failed");
exit (1);
}
int i;
for (i = 1; i < 32; ++i)
if (sigismember (&ss, i) && ! sigismember (&ss2, i))
{
printf ("signal %d set in parent mask, but not in child\n", i);
exit (1);
}
else if (! sigismember (&ss, i) && sigismember (&ss2, i))
{
printf ("signal %d set in child mask, but not in parent\n", i);
exit (1);
}
return NULL;
}
static int
do_test (void)
{
sigemptyset (&ss);
sigaddset (&ss, SIGUSR1);
if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
{
puts ("1st sigmask failed");
exit (1);
}
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("1st create failed");
exit (1);
}
void *r;
if (pthread_join (th, &r) != 0)
{
puts ("1st join failed");
exit (1);
}
sigemptyset (&ss);
sigaddset (&ss, SIGUSR2);
sigaddset (&ss, SIGFPE);
if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
{
puts ("2nd sigmask failed");
exit (1);
}
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("2nd create failed");
exit (1);
}
if (pthread_join (th, &r) != 0)
{
puts ("2nd join failed");
exit (1);
}
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,197 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef SIGRTMIN
# define N 2
static pthread_barrier_t bar;
static struct
{
void *p;
pthread_t s;
} ti[N];
static int sig1;
static void
handler (int sig)
{
pthread_t self = pthread_self ();
size_t i;
for (i = 0; i < N; ++i)
if (ti[i].s == self)
{
if ((uintptr_t) ti[i].p <= (uintptr_t) &self
&& (uintptr_t) ti[i].p + 2 * MINSIGSTKSZ > (uintptr_t) &self)
{
puts ("alt stack not used");
exit (1);
}
printf ("thread %zu used alt stack for signal %d\n", i, sig);
return;
}
puts ("handler: thread not found");
exit (1);
}
static void *
tf (void *arg)
{
size_t nr = (uintptr_t) arg;
if (nr >= N)
{
puts ("wrong nr parameter");
exit (1);
}
sigset_t ss;
sigemptyset (&ss);
size_t i;
for (i = 0; i < N; ++i)
if (i != nr)
if (sigaddset (&ss, sig1 + i) != 0)
{
puts ("tf: sigaddset failed");
exit (1);
}
if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
{
puts ("tf: sigmask failed");
exit (1);
}
void *p = malloc (2 * MINSIGSTKSZ);
if (p == NULL)
{
puts ("tf: malloc failed");
exit (1);
}
stack_t s;
s.ss_sp = p;
s.ss_size = 2 * MINSIGSTKSZ;
s.ss_flags = 0;
if (sigaltstack (&s, NULL) != 0)
{
puts ("tf: sigaltstack failed");
exit (1);
}
ti[nr].p = p;
ti[nr].s = pthread_self ();
pthread_barrier_wait (&bar);
pthread_barrier_wait (&bar);
return NULL;
}
static int
do_test (void)
{
sig1 = SIGRTMIN;
if (sig1 + N > SIGRTMAX)
{
puts ("too few RT signals");
return 0;
}
struct sigaction sa;
sa.sa_handler = handler;
sa.sa_flags = 0;
sigemptyset (&sa.sa_mask);
if (sigaction (sig1, &sa, NULL) != 0
|| sigaction (sig1 + 1, &sa, NULL) != 0
|| sigaction (sig1 + 2, &sa, NULL) != 0)
{
puts ("sigaction failed");
return 1;
}
if (pthread_barrier_init (&bar, NULL, 1 + N) != 0)
{
puts ("barrier_init failed");
return 1;
}
pthread_t th[N];
size_t i;
for (i = 0; i < N; ++i)
if (pthread_create (&th[i], NULL, tf, (void *) (long int) i) != 0)
{
puts ("create failed");
return 1;
}
/* Block the three signals. */
sigset_t ss;
sigemptyset (&ss);
for (i = 0; i <= N; ++i)
sigaddset (&ss, sig1 + i);
if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
{
puts ("main: sigmask failed");
return 1;
}
pthread_barrier_wait (&bar);
/* Send some signals. */
pid_t me = getpid ();
kill (me, sig1 + N);
for (i = 0; i < N; ++i)
kill (me, sig1 + i);
kill (me, sig1 + N);
/* Give the signals a chance to be worked on. */
sleep (1);
pthread_barrier_wait (&bar);
for (i = 0; i < N; ++i)
if (pthread_join (th[i], NULL) != 0)
{
puts ("join failed");
return 1;
}
return 0;
}
# define TEST_FUNCTION do_test ()
#else
# define TEST_FUNCTION 0
#endif
#include "../test-skeleton.c"

View File

@ -0,0 +1,62 @@
/* Tests for sigisemptyset and pthread_sigmask.
Copyright (C) 2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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
<https://www.gnu.org/licenses/>. */
#include <signal.h>
#include <support/check.h>
#include <support/xthread.h>
static void *
tf (void *arg)
{
{
sigset_t set;
sigemptyset (&set);
TEST_COMPARE (pthread_sigmask (SIG_BLOCK, 0, &set), 0);
TEST_COMPARE (sigisemptyset (&set), 1);
}
{
sigset_t set;
sigfillset (&set);
TEST_COMPARE (pthread_sigmask (SIG_BLOCK, 0, &set), 0);
TEST_COMPARE (sigisemptyset (&set), 1);
}
return NULL;
}
static int
do_test (void)
{
/* Ensure current SIG_BLOCK mask empty. */
{
sigset_t set;
sigemptyset (&set);
TEST_COMPARE (sigprocmask (SIG_BLOCK, &set, 0), 0);
}
{
pthread_t thr = xpthread_create (NULL, tf, NULL);
xpthread_join (thr);
}
return 0;
}
#include <support/test-driver.c>

View File

@ -0,0 +1,148 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <limits.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/param.h>
#include <unistd.h>
static void *stack;
static size_t size;
static void *
tf (void *a)
{
int result = 0;
puts ("child start");
pthread_attr_t attr;
if (pthread_getattr_np (pthread_self (), &attr) != 0)
{
puts ("getattr_np failed");
exit (1);
}
size_t test_size;
void *test_stack;
if (pthread_attr_getstack (&attr, &test_stack, &test_size) != 0)
{
puts ("attr_getstack failed");
exit (1);
}
if (test_size != size)
{
printf ("child: reported size differs: is %zu, expected %zu\n",
test_size, size);
result = 1;
}
if (test_stack != stack)
{
printf ("child: reported stack address differs: is %p, expected %p\n",
test_stack, stack);
result = 1;
}
puts ("child OK");
return result ? (void *) 1l : NULL;
}
int
do_test (void)
{
int result = 0;
size = 4 * getpagesize ();
#ifdef PTHREAD_STACK_MIN
size = MAX (size, PTHREAD_STACK_MIN);
#endif
if (posix_memalign (&stack, getpagesize (), size) != 0)
{
puts ("out of memory while allocating the stack memory");
exit (1);
}
pthread_attr_t attr;
if (pthread_attr_init (&attr) != 0)
{
puts ("attr_init failed");
exit (1);
}
puts ("attr_setstack");
if (pthread_attr_setstack (&attr, stack, size) != 0)
{
puts ("attr_setstack failed");
exit (1);
}
size_t test_size;
void *test_stack;
puts ("attr_getstack");
if (pthread_attr_getstack (&attr, &test_stack, &test_size) != 0)
{
puts ("attr_getstack failed");
exit (1);
}
if (test_size != size)
{
printf ("reported size differs: is %zu, expected %zu\n",
test_size, size);
result = 1;
}
if (test_stack != stack)
{
printf ("reported stack address differs: is %p, expected %p\n",
test_stack, stack);
result = 1;
}
puts ("create");
pthread_t th;
if (pthread_create (&th, &attr, tf, NULL) != 0)
{
puts ("failed to create thread");
exit (1);
}
void *status;
if (pthread_join (th, &status) != 0)
{
puts ("join failed");
exit (1);
}
result |= status != NULL;
return result;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,56 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
static int do_test (void);
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
static void *tf (void *a)
{
flockfile (stdout);
/* This call should never return. */
return a;
}
int
do_test (void)
{
pthread_t th;
flockfile (stdout);
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
write_message ("create failed\n");
_exit (1);
}
delayed_exit (1);
xpthread_join (th);
puts ("join returned");
return 1;
}

View File

@ -0,0 +1,82 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int do_test (void);
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"
static void *tf (void *a)
{
puts ("start tf");
/* Multiple locking, implicitly or explicitly, must be possible. */
flockfile (stdout);
puts ("after first flockfile");
flockfile (stdout);
puts ("foo");
funlockfile (stdout);
puts ("after first funlockfile");
funlockfile (stdout);
puts ("all done");
return a;
}
int
do_test (void)
{
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
write_message ("create failed\n");
_exit (1);
}
void *result;
if (pthread_join (th, &result) != 0)
{
puts ("join failed");
exit (1);
}
else if (result != NULL)
{
printf ("wrong return value: %p, expected %p\n", result, NULL);
exit (1);
}
puts ("join returned succsefully");
return 0;
}

117
sysdeps/pthread/tst-tsd1.c Normal file
View File

@ -0,0 +1,117 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <string.h>
static int
do_test (void)
{
pthread_key_t key1;
pthread_key_t key2;
void *value;
int result = 0;
int err;
err = pthread_key_create (&key1, NULL);
if (err != 0)
{
printf ("1st key_create failed: %s\n", strerror (err));
return 1;
}
/* Initial value must be NULL. */
value = pthread_getspecific (key1);
if (value != NULL)
{
puts ("1st getspecific != NULL");
result = 1;
}
err = pthread_setspecific (key1, (void *) -2l);
if (err != 0)
{
printf ("1st setspecific failed: %s\n", strerror (err));
return 1;
}
value = pthread_getspecific (key1);
if (value == NULL)
{
puts ("2nd getspecific == NULL\n");
result = 1;
}
else if (value != (void *) -2l)
{
puts ("2nd getspecific != -2l\n");
result = 1;
}
err = pthread_setspecific (key1, (void *) -3l);
if (err != 0)
{
printf ("2nd setspecific failed: %s\n", strerror (err));
return 1;
}
value = pthread_getspecific (key1);
if (value == NULL)
{
puts ("3rd getspecific == NULL\n");
result = 1;
}
else if (value != (void *) -3l)
{
puts ("3rd getspecific != -2l\n");
result = 1;
}
err = pthread_key_delete (key1);
if (err != 0)
{
printf ("key_delete failed: %s\n", strerror (err));
result = 1;
}
err = pthread_key_create (&key2, NULL);
if (err != 0)
{
printf ("2nd key_create failed: %s\n", strerror (err));
return 1;
}
if (key1 != key2)
puts ("key1 != key2; no more tests performed");
else
{
value = pthread_getspecific (key2);
if (value != NULL)
{
puts ("4th getspecific != NULL");
result = 1;
}
}
return result;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,96 @@
/* Copyright (C) 2002-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <string.h>
static int result;
static void
destr (void *arg)
{
if (arg != (void *) -2l)
result = 2;
else
result = 0;
}
static void *
tf (void *arg)
{
pthread_key_t key = (pthread_key_t) (long int) arg;
int err;
err = pthread_setspecific (key, (void *) -2l);
if (err != 0)
result = 3;
return NULL;
}
static int
do_test (void)
{
pthread_key_t key;
pthread_t th;
int err;
err = pthread_key_create (&key, destr);
if (err != 0)
{
printf ("key_create failed: %s\n", strerror (err));
return 1;
}
result = 1;
err = pthread_create (&th, NULL, tf, (void *) (long int) key);
if (err != 0)
{
printf ("create failed: %s\n", strerror (err));
return 1;
}
/* Wait for the thread to terminate. */
err = pthread_join (th, NULL);
if (err != 0)
{
printf ("join failed: %s\n", strerror (err));
return 1;
}
if (result == 1)
puts ("destructor not called");
else if (result == 2)
puts ("destructor got passed a wrong value");
else if (result == 3)
puts ("setspecific in child failed");
else if (result != 0)
puts ("result != 0");
return result;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,80 @@
/* Copyright (C) 2004-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
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
<https://www.gnu.org/licenses/>. */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
static void
cl (void *p)
{
pthread_mutex_unlock (&m);
}
static void *
tf (void *arg)
{
if (pthread_mutex_lock (&m) != 0)
{
puts ("2nd mutex_lock failed");
exit (1);
}
exit (0);
}
static int
do_test (void)
{
pthread_key_t k;
if (pthread_key_create (&k, cl) != 0)
{
puts ("key_create failed");
return 1;
}
if (pthread_setspecific (k, (void *) 1) != 0)
{
puts ("setspecific failed");
return 1;
}
if (pthread_mutex_lock (&m) != 0)
{
puts ("1st mutex_lock failed");
return 1;
}
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
return 1;
}
pthread_exit (NULL);
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,89 @@
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define NKEYS 100
static pthread_key_t keys[NKEYS];
static pthread_barrier_t b;
static void *
tf (void *arg)
{
void *res = NULL;
for (int i = 0; i < NKEYS; ++i)
{
void *p = pthread_getspecific (keys[i]);
pthread_setspecific (keys[i], (void *) 7);
if (p != NULL)
res = p;
}
if (arg != NULL)
{
pthread_barrier_wait (arg);
pthread_barrier_wait (arg);
}
return res;
}
static int
do_test (void)
{
pthread_barrier_init (&b, NULL, 2);
for (int i = 0; i < NKEYS; ++i)
if (pthread_key_create (&keys[i], NULL) != 0)
{
puts ("cannot create keys");
return 1;
}
pthread_t th;
if (pthread_create (&th, NULL, tf, &b) != 0)
{
puts ("cannot create thread in parent");
return 1;
}
pthread_barrier_wait (&b);
pid_t pid = fork ();
if (pid == 0)
{
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("cannot create thread in child");
exit (1);
}
void *res;
pthread_join (th, &res);
exit (res != NULL);
}
else if (pid == -1)
{
puts ("cannot create child process");
return 1;
}
int s;
if (TEMP_FAILURE_RETRY (waitpid (pid, &s, 0)) != pid)
{
puts ("failing to wait for child process");
return 1;
}
pthread_barrier_wait (&b);
pthread_join (th, NULL);
return !WIFEXITED (s) ? 2 : WEXITSTATUS (s);
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,136 @@
/* Copyright (C) 2003-2020 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
<https://www.gnu.org/licenses/>. */
#include <fcntl.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
static struct
{
int (*fp) (const char *, mode_t);
const char *name;
bool is_fd;
} fcts[] =
{
{ creat, "creat", true },
{ mkdir, "mkdir", false },
{ mkfifo, "mkfifo", false },
};
#define nfcts (sizeof (fcts) / sizeof (fcts[0]))
static int
work (const char *fname, int mask)
{
int result = 0;
size_t i;
for (i = 0; i < nfcts; ++i)
{
remove (fname);
int fd = fcts[i].fp (fname, 0777);
if (fd == -1)
{
printf ("cannot %s %s: %m\n", fcts[i].name, fname);
exit (1);
}
if (fcts[i].is_fd)
close (fd);
struct stat64 st;
if (stat64 (fname, &st) == -1)
{
printf ("cannot stat %s after %s: %m\n", fname, fcts[i].name);
exit (1);
}
if ((st.st_mode & mask) != 0)
{
printf ("mask not successful after %s: %x still set\n",
fcts[i].name, (unsigned int) (st.st_mode & mask));
result = 1;
}
}
return result;
}
static pthread_barrier_t bar;
static void *
tf (void *arg)
{
pthread_barrier_wait (&bar);
int result = work (arg, 022);
pthread_barrier_wait (&bar);
pthread_barrier_wait (&bar);
return (work (arg, 0) | result) ? (void *) -1l : NULL;
}
static int
do_test (const char *fname)
{
int result = 0;
umask (0);
result |= work (fname, 0);
pthread_barrier_init (&bar, NULL, 2);
pthread_t th;
if (pthread_create (&th, NULL, tf, (void *) fname) != 0)
{
puts ("cannot create thread");
exit (1);
}
umask (022);
result |= work (fname, 022);
pthread_barrier_wait (&bar);
pthread_barrier_wait (&bar);
umask (0);
pthread_barrier_wait (&bar);
void *res;
if (pthread_join (th, &res) != 0)
{
puts ("join failed");
exit (1);
}
remove (fname);
return result || res != NULL;
}
#define TEST_FUNCTION do_test (argc < 2 ? "/tmp/tst-umask.tmp" : argv[1])
#include "../test-skeleton.c"

View File

@ -0,0 +1,47 @@
/* Tests for non-unloading of libpthread.
Copyright (C) 2000-2020 Free Software Foundation, Inc.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2000.
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; see the file COPYING.LIB. If
not, see <https://www.gnu.org/licenses/>. */
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <gnu/lib-names.h>
static int
do_test (void)
{
void *p = dlopen (LIBPTHREAD_SO, RTLD_LAZY);
if (p == NULL)
{
puts ("failed to load " LIBPTHREAD_SO);
return 1;
}
if (dlclose (p) != 0)
{
puts ("dlclose (" LIBPTHREAD_SO ") failed");
return 1;
}
puts ("seems to work");
return 0;
}
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -0,0 +1,2 @@
#define USE_PTHREADS 1
#include "../elf/tst-unwind-main.c"

View File

@ -0,0 +1 @@
#include <posix/tst-vfork1.c>

View File

@ -0,0 +1 @@
#include <posix/tst-vfork2.c>