2003-12-18  Ulrich Drepper  <drepper@redhat.com>

	* tst-eintr1.c: Better error messages.

	* Makefile (tests): Add tst-eintr2.
	* tst-eintr2.c: New file.

2003-12-18  Jakub Jelinek  <jakub@redhat.com>

	* Makefile (tests): Add tst-cancel21 and tst-cancelx21.
	(CFLAGS-tst-cancelx21.c): Set.
	* tst-cancel21.c: New test.
	* tst-cancelx21.c: New test.

	* unwind.c (FRAME_LEFT): Add adj argument.  Subtract it from each
	comparison operand.
	(unwind_stop): Use _JMPBUF_CFA_UNWINDS_ADJ macro instead of
	_JMPBUF_CFA_UNWINDS.  Adjust FRAME_LEFT invocations.
	* pt-longjmp.c: Include jmpbuf-unwind.h.
	(__pthread_cleanup_upto): Use _JMPBUF_UNWINDS_ADJ macro instead of
	_JMPBUF_UNWINDS.  Adjust compared pointers.
	* init.c (__pthread_initialize_minimal_internal): Initialize
	pd->stackblock_size.
	* sysdeps/pthread/jmpbuf-unwind.h: Removed.
	* sysdeps/alpha/jmpbuf-unwind.h: New file.
	* sysdeps/i386/jmpbuf-unwind.h: New file.
	* sysdeps/powerpc/jmpbuf-unwind.h: New file.
	* sysdeps/s390/jmpbuf-unwind.h: New file.
	* sysdeps/sh/jmpbuf-unwind.h: New file.
	* sysdeps/sparc/sparc32/jmpbuf-unwind.h: New file.
	* sysdeps/x86_64/jmpbuf-unwind.h: New file.
	* sysdeps/ia64/jmpbuf-unwind.h: Include stdint.h.
	(_JMPBUF_CFA_UNWINDS): Remove.
	(_JMPBUF_CFA_UNWINDS_ADJ, _JMPBUF_UNWINDS_ADJ): Define.

2003-12-12  Jakub Jelinek  <jakub@redhat.com>

	* Makefile (tests): Add tst-cancel20 and tst-cancelx20.
	(CFLAGS-tst-cancelx20.c): Set.
	* tst-cancel20.c: New test.
	* tst-cancelx20.c: New test.
This commit is contained in:
Ulrich Drepper 2003-12-19 01:37:13 +00:00
parent 3434f15222
commit 675620f74c
19 changed files with 953 additions and 25 deletions

View File

@ -1,3 +1,45 @@
2003-12-18 Ulrich Drepper <drepper@redhat.com>
* tst-eintr1.c: Better error messages.
* Makefile (tests): Add tst-eintr2.
* tst-eintr2.c: New file.
2003-12-18 Jakub Jelinek <jakub@redhat.com>
* Makefile (tests): Add tst-cancel21 and tst-cancelx21.
(CFLAGS-tst-cancelx21.c): Set.
* tst-cancel21.c: New test.
* tst-cancelx21.c: New test.
* unwind.c (FRAME_LEFT): Add adj argument. Subtract it from each
comparison operand.
(unwind_stop): Use _JMPBUF_CFA_UNWINDS_ADJ macro instead of
_JMPBUF_CFA_UNWINDS. Adjust FRAME_LEFT invocations.
* pt-longjmp.c: Include jmpbuf-unwind.h.
(__pthread_cleanup_upto): Use _JMPBUF_UNWINDS_ADJ macro instead of
_JMPBUF_UNWINDS. Adjust compared pointers.
* init.c (__pthread_initialize_minimal_internal): Initialize
pd->stackblock_size.
* sysdeps/pthread/jmpbuf-unwind.h: Removed.
* sysdeps/alpha/jmpbuf-unwind.h: New file.
* sysdeps/i386/jmpbuf-unwind.h: New file.
* sysdeps/powerpc/jmpbuf-unwind.h: New file.
* sysdeps/s390/jmpbuf-unwind.h: New file.
* sysdeps/sh/jmpbuf-unwind.h: New file.
* sysdeps/sparc/sparc32/jmpbuf-unwind.h: New file.
* sysdeps/x86_64/jmpbuf-unwind.h: New file.
* sysdeps/ia64/jmpbuf-unwind.h: Include stdint.h.
(_JMPBUF_CFA_UNWINDS): Remove.
(_JMPBUF_CFA_UNWINDS_ADJ, _JMPBUF_UNWINDS_ADJ): Define.
2003-12-12 Jakub Jelinek <jakub@redhat.com>
* Makefile (tests): Add tst-cancel20 and tst-cancelx20.
(CFLAGS-tst-cancelx20.c): Set.
* tst-cancel20.c: New test.
* tst-cancelx20.c: New test.
2003-12-17 Ulrich Drepper <drepper@redhat.com>
* init.c (__pthread_initialize_minimal_internal): Don't treat

View File

@ -207,7 +207,7 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 \
tst-detach1 \
tst-eintr1 \
tst-eintr1 tst-eintr2 \
tst-tsd1 tst-tsd2 tst-tsd3 tst-tsd4 \
tst-tls1 tst-tls2 \
tst-fork1 tst-fork2 tst-fork3 tst-fork4 \
@ -215,7 +215,8 @@ tests = tst-attr1 tst-attr2 tst-attr3 \
tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel4 tst-cancel5 \
tst-cancel6 tst-cancel7 tst-cancel8 tst-cancel9 tst-cancel10 \
tst-cancel11 tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 \
tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 \
tst-cancel16 tst-cancel17 tst-cancel18 tst-cancel19 tst-cancel20 \
tst-cancel21 \
tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 tst-cleanup4 \
tst-flock1 tst-flock2 \
tst-signal1 tst-signal2 tst-signal3 tst-signal4 tst-signal5 \
@ -246,8 +247,8 @@ include ../Makeconfig
ifeq ($(have-forced-unwind),yes)
tests += tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx5 \
tst-cancelx6 tst-cancelx7 tst-cancelx8 tst-cancelx9 tst-cancelx10 \
tst-cancelx11 tst-cancelx12 tst-cancelx13 tst-cancelx14 tst-cancelx15\
tst-cancelx16 tst-cancelx17 tst-cancelx18 \
tst-cancelx11 tst-cancelx12 tst-cancelx13 tst-cancelx14 tst-cancelx15 \
tst-cancelx16 tst-cancelx17 tst-cancelx18 tst-cancelx20 tst-cancelx21 \
tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 \
tst-oncex3 tst-oncex4
endif
@ -388,6 +389,8 @@ CFLAGS-tst-cancelx15.c += -fexceptions
CFLAGS-tst-cancelx16.c += -fexceptions
CFLAGS-tst-cancelx17.c += -fexceptions
CFLAGS-tst-cancelx18.c += -fexceptions
CFLAGS-tst-cancelx20.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-tst-cancelx21.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-tst-cleanupx0.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-tst-cleanupx1.c += -fexceptions -fasynchronous-unwind-tables
CFLAGS-tst-cleanupx2.c += -fexceptions

View File

@ -217,6 +217,14 @@ __pthread_initialize_minimal_internal (void)
THREAD_SETMEM (pd, cpuclock_offset, GL(dl_cpuclock_offset));
#endif
/* Defined in ld.so. */
extern void *__libc_stack_end;
/* Set initial thread's stack block from 0 up to __libc_stack_end.
It will be bigger than it actually is, but for unwind.c/pt-longjmp.c
purposes this is good enough. */
THREAD_SETMEM (pd, stackblock_size, (size_t) __libc_stack_end);
/* Initialize the list of all running threads with the main thread. */
INIT_LIST_HEAD (&__stack_user);
list_add (&pd->list, &__stack_user);

View File

@ -20,7 +20,7 @@
#include <setjmp.h>
#include <stdlib.h>
#include "pthreadP.h"
#include "jmpbuf-unwind.h"
void
__pthread_cleanup_upto (__jmp_buf target, char *targetframe)
@ -28,18 +28,24 @@ __pthread_cleanup_upto (__jmp_buf target, char *targetframe)
struct pthread *self = THREAD_SELF;
struct _pthread_cleanup_buffer *cbuf;
/* Adjust all pointers used in comparisons, so that top of thread's
stack is at the top of address space. Without that, things break
if stack is allocated above the main stack. */
uintptr_t adj = (uintptr_t) self->stackblock + self->stackblock_size;
uintptr_t targetframe_adj = (uintptr_t) targetframe - adj;
for (cbuf = THREAD_GETMEM (self, cleanup);
cbuf != NULL && _JMPBUF_UNWINDS (target, cbuf);
cbuf != NULL && _JMPBUF_UNWINDS_ADJ (target, cbuf, adj);
cbuf = cbuf->__prev)
{
#if _STACK_GROWS_DOWN
if ((char *) cbuf <= targetframe)
if ((uintptr_t) cbuf - adj <= targetframe_adj)
{
cbuf = NULL;
break;
}
#elif _STACK_GROWS_UP
if ((char *) cbuf >= targetframe)
if ((uintptr_t) cbuf - adj >= targetframe_adj)
{
cbuf = NULL;
break;

View File

@ -18,7 +18,11 @@
02111-1307 USA. */
#include <setjmp.h>
#include <stdint.h>
#include <unwind.h>
#define _JMPBUF_CFA_UNWINDS(_jmpbuf, _context) \
_JMPBUF_UNWINDS (_jmpbuf, (void *) _Unwind_GetCFA (_context))
#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
_JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj))

View File

@ -0,0 +1,28 @@
/* Copyright (C) 2003 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <setjmp.h>
#include <stdint.h>
#include <unwind.h>
#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
_JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj))

View File

@ -0,0 +1,28 @@
/* Copyright (C) 2003 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <setjmp.h>
#include <stdint.h>
#include <unwind.h>
#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
_JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_GPR1] - (_adj))

View File

@ -0,0 +1,29 @@
/* Copyright (C) 2003 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <setjmp.h>
#include <stdint.h>
#include <unwind.h>
#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
_JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
((uintptr_t) (_address) - (_adj) \
< (uintptr_t) (_jmpbuf)->__gregs[__JB_GPR15] - (_adj))

View File

@ -0,0 +1,28 @@
/* Copyright (C) 2003 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <setjmp.h>
#include <stdint.h>
#include <unwind.h>
#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
_JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
#define _JMPBUF_UNWINDS_ADJ(jmpbuf, address, adj) \
((uintptr_t) (address) - (adj) < (uintptr_t) (_jmpbuf)[0].__regs[7] - (adj))

View File

@ -0,0 +1,28 @@
/* Copyright (C) 2003 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <setjmp.h>
#include <stdint.h>
#include <unwind.h>
#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
_JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj))

View File

@ -18,12 +18,16 @@
02111-1307 USA. */
#include <setjmp.h>
#include <stdint.h>
#include <unwind.h>
#define _JMPBUF_CFA_UNWINDS(_jmpbuf, _context) \
({ void *_cfa = (void *) _Unwind_GetCFA (_context); \
(_cfa < (void *)(((long *)(_jmpbuf))[0]) \
|| (_cfa == (void *)(((long *)(_jmpbuf))[0]) \
&& (void *) _Unwind_GetBSP (_context) \
>= (void *)(((long *)(_jmpbuf))[17]))); \
#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
({ uintptr_t _cfa = (uintptr_t) _Unwind_GetCFA (_context) - (_adj); \
(_cfa < (uintptr_t)(((long *)(_jmpbuf))[0]) - (_adj) \
|| (_cfa == (uintptr_t)(((long *)(_jmpbuf))[0]) - (_adj) \
&& (uintptr_t) _Unwind_GetBSP (_context) - (_adj) \
>= (uintptr_t)(((long *)(_jmpbuf))[17]) - (_adj))); \
})
#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
((uintptr_t)(_address) - (_adj) < (uintptr_t)(((long *)_jmpbuf)[0]) - (_adj))

View File

@ -0,0 +1,28 @@
/* Copyright (C) 2003 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <setjmp.h>
#include <stdint.h>
#include <unwind.h>
#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
_JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_RSP] - (_adj))

263
nptl/tst-cancel20.c Normal file
View File

@ -0,0 +1,263 @@
/* Copyright (C) 2003 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
static int fd[4];
static pthread_barrier_t b;
volatile int in_sh_body;
unsigned long cleanups;
static void
cl (void *arg)
{
cleanups = (cleanups << 4) | (long) arg;
}
static void __attribute__((noinline))
sh_body (void)
{
char c;
pthread_cleanup_push (cl, (void *) 1L);
in_sh_body = 1;
if (read (fd[2], &c, 1) == 1)
{
puts ("read succeeded");
exit (1);
}
pthread_cleanup_pop (0);
}
static void
sh (int sig)
{
pthread_cleanup_push (cl, (void *) 2L);
sh_body ();
in_sh_body = 0;
pthread_cleanup_pop (0);
}
static void __attribute__((noinline))
tf_body (void)
{
char c;
pthread_cleanup_push (cl, (void *) 3L);
int r = pthread_barrier_wait (&b);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("child thread: barrier_wait failed");
exit (1);
}
if (read (fd[0], &c, 1) == 1)
{
puts ("read succeeded");
exit (1);
}
read (fd[0], &c, 1);
pthread_cleanup_pop (0);
}
static void *
tf (void *arg)
{
pthread_cleanup_push (cl, (void *) 4L);
tf_body ();
pthread_cleanup_pop (0);
return NULL;
}
static int
do_one_test (void)
{
cleanups = 0;
if (pipe (fd) != 0 || pipe (fd + 2) != 0)
{
puts ("pipe failed");
return 1;
}
pthread_t th;
if (pthread_create (&th, NULL, tf, NULL) != 0)
{
puts ("create failed");
return 1;
}
int r = pthread_barrier_wait (&b);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("parent thread: barrier_wait failed");
return 1;
}
sleep (1);
r = pthread_kill (th, SIGHUP);
if (r)
{
errno = r;
printf ("pthread_kill failed %m\n");
return 1;
}
while (in_sh_body == 0)
sleep (1);
if (pthread_cancel (th) != 0)
{
puts ("cancel failed");
return 1;
}
/* This will cause the read in the child to return. */
close (fd[0]);
close (fd[1]);
close (fd[2]);
close (fd[3]);
void *ret;
if (pthread_join (th, &ret) != 0)
{
puts ("join failed");
return 1;
}
if (ret != PTHREAD_CANCELED)
{
puts ("result is wrong");
return 1;
}
if (cleanups != 0x1234L)
{
printf ("called cleanups %lx\n", cleanups);
return 1;
}
return 0;
}
static int
do_test (void)
{
stack_t ss;
ss.ss_sp = malloc (2 * SIGSTKSZ);
if (ss.ss_sp == NULL)
{
puts ("failed to allocate alternate stack");
return 1;
}
ss.ss_flags = 0;
ss.ss_size = 2 * SIGSTKSZ;
if (sigaltstack (&ss, NULL) < 0)
{
printf ("sigaltstack failed %m\n");
return 1;
}
if (pthread_barrier_init (&b, NULL, 2) != 0)
{
puts ("barrier_init failed");
return 1;
}
struct sigaction sa;
sa.sa_handler = sh;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction (SIGHUP, &sa, NULL) != 0)
{
puts ("sigaction failed");
return 1;
}
puts ("sa_flags = 0 test");
if (do_one_test ())
return 1;
sa.sa_handler = sh;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_ONSTACK;
if (sigaction (SIGHUP, &sa, NULL) != 0)
{
puts ("sigaction failed");
return 1;
}
puts ("sa_flags = SA_ONSTACK test");
if (do_one_test ())
return 1;
sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction (SIGHUP, &sa, NULL) != 0)
{
puts ("sigaction failed");
return 1;
}
puts ("sa_flags = SA_SIGINFO test");
if (do_one_test ())
return 1;
sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
if (sigaction (SIGHUP, &sa, NULL) != 0)
{
puts ("sigaction failed");
return 1;
}
puts ("sa_flags = SA_SIGINFO|SA_ONSTACK test");
if (do_one_test ())
return 1;
return 0;
}
#define TIMEOUT 40
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

292
nptl/tst-cancel21.c Normal file
View File

@ -0,0 +1,292 @@
/* Copyright (C) 2003 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
static int fd[4];
static pthread_barrier_t b;
volatile int in_sh_body;
unsigned long cleanups;
static void
cl (void *arg)
{
cleanups = (cleanups << 4) | (long) arg;
}
static void __attribute__((noinline))
sh_body (void)
{
char c;
pthread_cleanup_push (cl, (void *) 1L);
in_sh_body = 1;
if (read (fd[2], &c, 1) == 1)
{
puts ("read succeeded");
exit (1);
}
pthread_cleanup_pop (0);
}
static void
sh (int sig)
{
pthread_cleanup_push (cl, (void *) 2L);
sh_body ();
in_sh_body = 0;
pthread_cleanup_pop (0);
}
static void __attribute__((noinline))
tf_body (void)
{
char c;
pthread_cleanup_push (cl, (void *) 3L);
int r = pthread_barrier_wait (&b);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("child thread: barrier_wait failed");
exit (1);
}
if (read (fd[0], &c, 1) == 1)
{
puts ("read succeeded");
exit (1);
}
read (fd[0], &c, 1);
pthread_cleanup_pop (0);
}
static void *
tf (void *arg)
{
pthread_t th = (pthread_t) arg;
int r = pthread_barrier_wait (&b);
if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
{
puts ("parent thread: barrier_wait failed");
exit (1);
}
sleep (1);
r = pthread_kill (th, SIGHUP);
if (r)
{
errno = r;
printf ("pthread_kill failed %m\n");
exit (1);
}
while (in_sh_body == 0)
sleep (1);
if (pthread_cancel (th) != 0)
{
puts ("cancel failed");
exit (1);
}
/* This will cause the read in the initial thread to return. */
close (fd[0]);
close (fd[1]);
close (fd[2]);
close (fd[3]);
void *ret;
if (pthread_join (th, &ret) != 0)
{
puts ("join failed");
exit (1);
}
if (ret != PTHREAD_CANCELED)
{
puts ("result is wrong");
exit (1);
}
if (cleanups != 0x1234L)
{
printf ("called cleanups %lx\n", cleanups);
exit (1);
}
if (pthread_barrier_destroy (&b))
{
puts ("barrier destroy failed");
exit (1);
}
exit (0);
}
static int
do_one_test (void)
{
pid_t pid = fork ();
if (pid == -1)
{
printf ("fork failed: %m\n");
return 1;
}
if (pid)
{
int status;
if (waitpid (pid, &status, 0) < 0)
{
printf ("waitpid failed %m\n");
return 1;
}
return !WIFEXITED (status) || WEXITSTATUS (status);
}
if (pthread_barrier_init (&b, NULL, 2) != 0)
{
puts ("barrier_init failed");
exit (1);
}
cleanups = 0;
if (pipe (fd) != 0 || pipe (fd + 2) != 0)
{
puts ("pipe failed");
exit (1);
}
pthread_t th;
if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
{
puts ("create failed");
exit (1);
}
pthread_cleanup_push (cl, (void *) 4L);
tf_body ();
pthread_cleanup_pop (0);
exit (1);
}
static int
do_test (void)
{
stack_t ss;
ss.ss_sp = malloc (2 * SIGSTKSZ);
if (ss.ss_sp == NULL)
{
puts ("failed to allocate alternate stack");
return 1;
}
ss.ss_flags = 0;
ss.ss_size = 2 * SIGSTKSZ;
if (sigaltstack (&ss, NULL) < 0)
{
printf ("sigaltstack failed %m\n");
return 1;
}
struct sigaction sa;
sa.sa_handler = sh;
sigemptyset (&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction (SIGHUP, &sa, NULL) != 0)
{
puts ("sigaction failed");
return 1;
}
puts ("sa_flags = 0 test");
if (do_one_test ())
return 1;
sa.sa_handler = sh;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_ONSTACK;
if (sigaction (SIGHUP, &sa, NULL) != 0)
{
puts ("sigaction failed");
return 1;
}
puts ("sa_flags = SA_ONSTACK test");
if (do_one_test ())
return 1;
sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction (SIGHUP, &sa, NULL) != 0)
{
puts ("sigaction failed");
return 1;
}
puts ("sa_flags = SA_SIGINFO test");
if (do_one_test ())
return 1;
sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
if (sigaction (SIGHUP, &sa, NULL) != 0)
{
puts ("sigaction failed");
return 1;
}
puts ("sa_flags = SA_SIGINFO|SA_ONSTACK test");
if (do_one_test ())
return 1;
return 0;
}
#define TIMEOUT 40
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

1
nptl/tst-cancelx20.c Normal file
View File

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

1
nptl/tst-cancelx21.c Normal file
View File

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

View File

@ -22,6 +22,7 @@
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "eintr.c"
@ -49,7 +50,9 @@ tf1 (void *arg)
exit (1);
}
puts ("pthread_create failed");
char buf[100];
printf ("tf1: pthread_create failed: %s\n",
strerror_r (e, buf, sizeof (buf)));
exit (1);
}
@ -62,7 +65,9 @@ tf1 (void *arg)
exit (1);
}
puts ("join failed");
char buf[100];
printf ("tf1: pthread_join failed: %s\n",
strerror_r (e, buf, sizeof (buf)));
exit (1);
}
}
@ -78,9 +83,12 @@ do_test (void)
for (i = 0; i < 10; ++i)
{
pthread_t th;
if (pthread_create (&th, NULL, tf1, NULL) != 0)
int e = pthread_create (&th, NULL, tf1, NULL);
if (e != 0)
{
puts ("pthread_create failed");
char buf[100];
printf ("main: pthread_create failed: %s\n",
strerror_r (e, buf, sizeof (buf)));
exit (1);
}
}

118
nptl/tst-eintr2.c Normal file
View File

@ -0,0 +1,118 @@
/* Copyright (C) 2003 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.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;
struct timeval tv;
gettimeofday (&tv, NULL);
TIMEVAL_TO_TIMESPEC (&tv, &ts);
ts.tv_sec += 10000;
/* This call must never return. */
int e = pthread_mutex_timedlock (&m1, &ts);
char buf[100];
printf ("tf1: mutex_lock returned: %s\n",
strerror_r (e, buf, sizeof (buf)));
exit (1);
}
static void *
tf2 (void *arg)
{
while (1)
{
int e = pthread_mutex_lock (&m2);
if (e != 0)
{
puts ("tf2: mutex_lock failed");
exit (1);
}
e = pthread_mutex_unlock (&m2);
if (e != 0)
{
puts ("tf2: mutex_unlock failed");
exit (1);
}
struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
nanosleep (&ts, NULL);
}
}
static int
do_test (void)
{
if (pthread_mutex_lock (&m1) != 0)
{
puts ("mutex_lock failed");
exit (1);
}
setup_eintr (SIGUSR1);
pthread_t th;
char buf[100];
int e = pthread_create (&th, NULL, tf1, NULL);
if (e != 0)
{
printf ("main: 1st pthread_create failed: %s\n",
strerror_r (e, buf, sizeof (buf)));
exit (1);
}
e = pthread_create (&th, NULL, tf2, NULL);
if (e != 0)
{
printf ("main: 2nd pthread_create failed: %s\n",
strerror_r (e, buf, sizeof (buf)));
exit (1);
}
/* This call must never return. */
e = pthread_mutex_lock (&m1);
printf ("main: mutex_lock returned: %s\n",
strerror_r (e, buf, sizeof (buf)));
return 0;
}
#define EXPECTED_SIGNAL SIGALRM
#define TIMEOUT 3
#define TEST_FUNCTION do_test ()
#include "../test-skeleton.c"

View File

@ -28,9 +28,11 @@
#ifdef HAVE_FORCED_UNWIND
#ifdef _STACK_GROWS_DOWN
# define FRAME_LEFT(frame, other) ((char *) frame >= (char *) other)
# define FRAME_LEFT(frame, other, adj) \
((uintptr_t) frame - adj >= (uintptr_t) other - adj)
#elif _STACK_GROWS_UP
# define FRAME_LEFT(frame, other) ((char *) frame <= (char *) other)
# define FRAME_LEFT(frame, other, adj) \
((uintptr_t) frame - adj <= (uintptr_t) other - adj)
#else
# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
#endif
@ -45,6 +47,11 @@ unwind_stop (int version, _Unwind_Action actions,
struct pthread *self = THREAD_SELF;
struct _pthread_cleanup_buffer *curp = THREAD_GETMEM (self, cleanup);
int do_longjump = 0;
/* Adjust all pointers used in comparisons, so that top of thread's
stack is at the top of address space. Without that, things break
if stack is allocated above the main stack. */
uintptr_t adj = (uintptr_t) self->stackblock + self->stackblock_size;
/* Do longjmp if we're at "end of stack", aka "end of unwind data".
We assume there are only C frame without unwind data in between
@ -52,7 +59,8 @@ unwind_stop (int version, _Unwind_Action actions,
of a function is NOT within it's stack frame; it's the SP of the
previous frame. */
if ((actions & _UA_END_OF_STACK)
|| ! _JMPBUF_CFA_UNWINDS (buf->cancel_jmp_buf[0].jmp_buf, context))
|| ! _JMPBUF_CFA_UNWINDS_ADJ (buf->cancel_jmp_buf[0].jmp_buf, context,
adj))
do_longjump = 1;
if (__builtin_expect (curp != NULL, 0))
@ -63,7 +71,7 @@ unwind_stop (int version, _Unwind_Action actions,
struct _pthread_cleanup_buffer *oldp = buf->priv.data.cleanup;
void *cfa = (void *) _Unwind_GetCFA (context);
if (curp != oldp && (do_longjump || FRAME_LEFT (cfa, curp)))
if (curp != oldp && (do_longjump || FRAME_LEFT (cfa, curp, adj)))
{
do
{
@ -76,7 +84,8 @@ unwind_stop (int version, _Unwind_Action actions,
/* To the next. */
curp = nextp;
}
while (curp != oldp && (do_longjump || FRAME_LEFT (cfa, curp)));
while (curp != oldp
&& (do_longjump || FRAME_LEFT (cfa, curp, adj)));
/* Mark the current element as handled. */
THREAD_SETMEM (self, cleanup, curp);