diff options
Diffstat (limited to 'nptl')
-rw-r--r-- | nptl/Makefile | 2 | ||||
-rw-r--r-- | nptl/allocatestack.c | 11 | ||||
-rw-r--r-- | nptl/tst-getpid3.c | 114 |
3 files changed, 123 insertions, 4 deletions
diff --git a/nptl/Makefile b/nptl/Makefile index 4023e46..d0f8286 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -256,7 +256,7 @@ tests = tst-typesizes \ tst-backtrace1 \ tst-oddstacklimit \ tst-vfork1 tst-vfork2 tst-vfork1x tst-vfork2x \ - tst-getpid1 tst-getpid2 \ + tst-getpid1 tst-getpid2 tst-getpid3 \ tst-initializers1 $(patsubst %,tst-initializers1-%,c89 gnu89 c99 gnu99) xtests = tst-setuid1 tst-setuid1-static diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index a3ed1a3..4a1cd18 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -742,9 +742,7 @@ __reclaim_stacks (void) list_t *runp; list_for_each (runp, &stack_used) { - struct pthread *curp; - - curp = list_entry (runp, struct pthread, list); + struct pthread *curp = list_entry (runp, struct pthread, list); if (curp != self) { /* This marks the stack as free. */ @@ -758,6 +756,13 @@ __reclaim_stacks (void) } } + /* Reset the PIDs in any cached stacks. */ + list_for_each (runp, &stack_cache) + { + struct pthread *curp = list_entry (runp, struct pthread, list); + curp->pid = self->pid; + } + /* Add the stack of all running threads to the cache. */ list_splice (&stack_used, &stack_cache); diff --git a/nptl/tst-getpid3.c b/nptl/tst-getpid3.c new file mode 100644 index 0000000..f1e77f6 --- /dev/null +++ b/nptl/tst-getpid3.c @@ -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" |