X-Git-Url: http://git.jankratochvil.net/?a=blobdiff_plain;f=testsuite.c;h=fce7c791c4e88984be7c4c9111d1516d32282a9a;hb=cc37c1111d15153e6bf397f0692fdfba1949fa4d;hp=242b53d716bbdf931c23c9380363a4f5359c4857;hpb=103e706d79f5f3e7aa16cab71c63fcad01b986c6;p=debugger.git diff --git a/testsuite.c b/testsuite.c index 242b53d..fce7c79 100644 --- a/testsuite.c +++ b/testsuite.c @@ -1,5 +1,7 @@ /* Copyright 2007, Red Hat Inc. */ +#define _GNU_SOURCE 1 + #include #include #include @@ -10,6 +12,7 @@ #include #include #include +#include #include "debugger.h" @@ -20,29 +23,42 @@ #define tkill(tid, sig) syscall (SYS_tkill, (tid), (sig)) -static int attach_checked (pid_t pid, int redelivered_expect) +static volatile int spawned_threads_count; /* Set for the specific spawner. */ + +static struct attach_state_struct *attach_checked (pid_t pid, int redelivered_expect) { - int stopped; + struct attach_state_struct *attach_state; STATE (pid, (1 << STATE_SLEEPING) | (1 << STATE_RUNNING) | (1 << STATE_STOPPED)); - stopped = attach (pid); - if (attach_redelivered != redelivered_expect) + attach_state = attach (pid); + if (redelivered_expect != attach_state_redelivered_get (attach_state)) { fprintf (stderr, "Expecting redelivery of %d but found %d\n", - redelivered_expect, attach_redelivered); + redelivered_expect, attach_state_redelivered_get (attach_state)); abort (); } + assert (spawned_threads_count == attach_state_threads_count_get (attach_state)); /* FIXME: Why also STATE_STOPPED? */ STATE (pid, (1 << STATE_PTRACED) | (1 << STATE_STOPPED)); - return stopped; + return attach_state; } -static void detach_checked (pid_t pid, int stopped) +static void detach_checked (struct attach_state_struct *attach_state) { - /* FIXME: Why STATE_STOPPED? */ - STATE (pid, (stopped ? 1 << STATE_STOPPED : 1 << STATE_PTRACED)); - detach (pid, stopped); - STATE (pid, (stopped ? 1 << STATE_STOPPED : (1 << STATE_SLEEPING) | (1 << STATE_RUNNING))); + pid_t pid = attach_state_pid_get (attach_state); + + if (attach_state_stopped_get (attach_state) != 0) + { + STATE (pid, 1 << STATE_STOPPED); + detach (attach_state); + STATE (pid, 1 << STATE_STOPPED); + } + else + { + STATE (pid, (1 << STATE_PTRACED)); + detach (attach_state); + STATE (pid, ((1 << STATE_SLEEPING) | (1 << STATE_RUNNING))); + } } struct registry @@ -122,7 +138,7 @@ static void registry_handler (int signo) raise (signo); } -static void child_pause (void) +static __attribute__((__noreturn__)) void child_pause (void) { for (;;) pause (); @@ -136,7 +152,7 @@ static void child_alrm_handler (int signo) raise (SIGALRM); } -static void child_alrm (void) +static __attribute__((__noreturn__)) void child_alrm (void) { void (*handler_orig) (int signo); #if 0 @@ -227,7 +243,7 @@ struct child_spawner int fd; }; -static void *child_spawner (void *param_voidpointer, void *input) +static __attribute__((__noreturn__)) void *child_spawner (void *param_voidpointer, void *input) { struct child_spawner *param = param_voidpointer; pid_t inferior; @@ -300,16 +316,16 @@ static void body_spawner (void *(*child) (void *data, void *input), void *data, void *input) { pid_t inferior; - int stopped; + struct attach_state_struct *attach_state; int i; assert (input == NULL); /* Plain attach/detach. */ inferior = (unsigned long) (*child) (data, child_pause); - stopped = attach_checked (inferior, 0); - assert (stopped == 0); - detach_checked (inferior, stopped); + attach_state = attach_checked (inferior, 0); + assert (attach_state_stopped_get (attach_state) == 0); + detach_checked (attach_state); murder (inferior); /* Attach to a process stopped by standard kill(2). */ @@ -318,9 +334,9 @@ static void body_spawner (void *(*child) (void *data, void *input), void *data, i = kill (inferior, SIGSTOP); assert (i == 0); STATE (inferior, 1 << STATE_STOPPED); - stopped = attach_checked (inferior, 0); - assert (stopped == 1); - detach_checked (inferior, stopped); + attach_state = attach_checked (inferior, 0); + assert (attach_state_stopped_get (attach_state) == 1); + detach_checked (attach_state); murder (inferior); /* Attach to a process stopped by Linux specific tkill(2). */ @@ -329,9 +345,9 @@ static void body_spawner (void *(*child) (void *data, void *input), void *data, i = tkill (inferior, SIGSTOP); assert (i == 0); STATE (inferior, 1 << STATE_STOPPED); - stopped = attach_checked (inferior, 0); - assert (stopped == 1); - detach_checked (inferior, stopped); + attach_state = attach_checked (inferior, 0); + assert (attach_state_stopped_get (attach_state) == 1); + detach_checked (attach_state); murder (inferior); /* Attach to a stopped process with already pending SIGALRM. */ @@ -348,12 +364,12 @@ static void body_spawner (void *(*child) (void *data, void *input), void *data, STATE (inferior, 1 << STATE_STOPPED); /* FIXME: SIGALRM did not get redelivered? */ #if 0 - stopped = attach_checked (inferior, SIGALRM); + attach_state = attach_checked (inferior, SIGALRM); #else - stopped = attach_checked (inferior, 0); + attach_state = attach_checked (inferior, 0); #endif - assert (stopped == 1); - detach_checked (inferior, stopped); + assert (attach_state_stopped_get (attach_state) == 1); + detach_checked (attach_state); STATE (inferior, 1 << STATE_STOPPED); delay (); i = tkill (inferior, SIGCONT); @@ -397,7 +413,7 @@ static void *spawn_singlethreaded (void *data, void *input) return pass (data, input); } -static void *spawn_threaded_parent_start (void *arg) +static __attribute__((__noreturn__)) void *spawn_threaded_parent_start (void *arg) { for (;;) pause (); @@ -405,12 +421,46 @@ static void *spawn_threaded_parent_start (void *arg) abort (); } +static void *libpthread_handle; +static int (*libpthread_create_pointer) (pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine) (void *), + void *arg); +static int (*libpthread_join_pointer) (pthread_t thread, void **value_ptr); + +static void libpthread_open (void) +{ + assert (libpthread_handle == NULL); + + libpthread_handle = dlopen ("libpthread.so.0", RTLD_LAZY); + assert (libpthread_handle != NULL); + + libpthread_create_pointer = dlsym (libpthread_handle, "pthread_create"); + assert (libpthread_create_pointer != NULL); + libpthread_join_pointer = dlsym (libpthread_handle, "pthread_join"); + assert (libpthread_join_pointer != NULL); + +} + +static void libpthread_close (void) +{ + int i; + + assert (libpthread_handle != NULL); + + i = dlclose (libpthread_handle); + assert (i == 0); + libpthread_handle = NULL; +} + static void *spawn_threaded_parent (void *data, void *input) { pthread_t thread; int i; - i = pthread_create (&thread, NULL, spawn_threaded_parent_start, NULL); + assert (libpthread_create_pointer != NULL); + i = (*libpthread_create_pointer) (&thread, NULL, spawn_threaded_parent_start, + NULL); assert (i == 0); return pass (data, input); } @@ -426,10 +476,9 @@ static void *spawn_threaded_child_start (void *arg_voidpointer) struct spawn_threaded_child_start *arg = arg_voidpointer; return pass (arg->data, arg->input); - /* NOTREACHED */ } -static void *spawn_threaded_child (void *data, void *input) +static __attribute__((__noreturn__)) void *spawn_threaded_child (void *data, void *input) { pthread_t thread; int i; @@ -437,12 +486,17 @@ static void *spawn_threaded_child (void *data, void *input) arg_local.data = data; arg_local.input = input; - i = pthread_create (&thread, NULL, spawn_threaded_child_start, &arg_local); + assert (libpthread_create_pointer != NULL); + i = (*libpthread_create_pointer) (&thread, NULL, spawn_threaded_child_start, + &arg_local); assert (i == 0); - i = pthread_join (thread, NULL); + assert (libpthread_join_pointer != NULL); + i = (*libpthread_join_pointer) (thread, NULL); assert (i == 0); _exit (EXIT_SUCCESS); + /* NOTREACHED */ + abort (); } static void body_maywaiter (void *(*child) (void *data, void *input), @@ -466,11 +520,34 @@ static void handler_sigusr1 (int signo) loops_print++; } +static __attribute__((__noreturn__)) void *tests_threaded (void *data, void *input) +{ + libpthread_open (); + + spawned_threads_count = 2; + body_maywaiter (spawn_threaded_parent, NULL, NULL); + + spawned_threads_count = 2; + body_maywaiter (spawn_threaded_child, NULL, NULL); + + libpthread_close (); + + registry_cleanup (); + _exit (EXIT_SUCCESS); + /* NOTREACHED */ + abort (); +} + int main (int argc, char **argv) { int loop = 0; int i; +#ifdef MEASURE_STATE_PERFORMANCE + STATE (1, 1 << STATE_ZOMBIE); + return 0; +#endif /* MEASURE_STATE_PERFORMANCE */ + if (argc == 1) ; else if (argc == 2 && strcmp (argv[1], "-l") == 0) @@ -489,19 +566,36 @@ int main (int argc, char **argv) do { + pid_t pid_threaded, pid_threaded_got; + int status; + while (loops_print > 0) { printf ("%lu\n", loops); loops_print--; } + + spawned_threads_count = 0; body_maywaiter (spawn_singlethreaded, NULL, NULL); - body_maywaiter (spawn_threaded_parent, NULL, NULL); - body_maywaiter (spawn_threaded_child, NULL, NULL); + + /* We cannot rely on LIBPTHREAD_CLOSE as libpthread would be still loaded + with ATTACH_STATE_REDELIVERED_GET () reporting 1 for + SPAWN_SINGLETHREADED. */ + pid_threaded = spawn (tests_threaded, NULL, NULL, -1); + pid_threaded_got = waitpid (pid_threaded, &status, 0); + assert (pid_threaded_got == pid_threaded); + assert (!WIFSIGNALED (status)); /* Improve readability in the failed case. */ + assert (!WIFSTOPPED (status)); /* Improve readability in the failed case. */ + assert (WIFEXITED (status)); + assert (WEXITSTATUS (status) == 0); + STATE (pid_threaded, 1 << STATE_ENOENT); + registry_remove (pid_threaded); registry_cleanup (); loops++; } - while (loop != 0); + /* Run at least twice to test libpthread_close (). */ + while (loop != 0 || loops == 1); return EXIT_SUCCESS; }