From: Jan Kiszka <[email protected]> Extend the gdb test with cases that stress the debugging helper thread. We check if the helper is run on hitting a breakpoint as well as before resuming the process afterwards.
This should be extended in the future by also testing error cases. Signed-off-by: Jan Kiszka <[email protected]> --- testsuite/smokey/gdb/gdb.c | 84 +++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/testsuite/smokey/gdb/gdb.c b/testsuite/smokey/gdb/gdb.c index eabf75e6a2..ff97debd32 100644 --- a/testsuite/smokey/gdb/gdb.c +++ b/testsuite/smokey/gdb/gdb.c @@ -18,6 +18,7 @@ #include <semaphore.h> #include <sys/wait.h> #include <xeno_config.h> +#include <cobalt/ptrace.h> #include <boilerplate/libc.h> #include <smokey/smokey.h> #include "lib/cobalt/current.h" @@ -65,10 +66,12 @@ smokey_test_plugin(gdb, static int pipe_in[2], pipe_out[2]; static volatile unsigned long long thread_loops, expected_loops; +static volatile unsigned int stop_events, cont_events; +static volatile int terminate, ptrace_helper_terminated; static volatile int primary_mode; -static volatile int terminate; static int child_terminated; -static sem_t kickoff_lo; +static sem_t kickoff_lo, kickoff_helper; +static pthread_t thread_ptrace_helper; static void handle_sigchld(int signum) { @@ -184,9 +187,61 @@ static void *thread_hi_func(void *arg) breakpoint_target(); /* 2nd bp: synchronous continue */ + breakpoint_target(); + + err = sem_post(&kickoff_helper); + check_no_error("sem_post", err); + + nanosleep(&ts, NULL); + + /* 3rd bp: synchronous stop with ptrace helper in place */ expected_loops = thread_loops; breakpoint_target(); + + /* 4th bp: synchronous continue with ptrace helper */ + breakpoint_target(); + + /* 5th bp: terminate ptrace helper (and spinning thread) */ terminate = 1; + err = pthread_cancel(thread_ptrace_helper); + check_no_error("pthread_cancel", err); + err = pthread_join(thread_ptrace_helper, NULL); + check_no_error("pthread_join", err); + ptrace_helper_terminated = 1; + breakpoint_target(); + + return NULL; +} + +static void *thread_ptrace_helper_func(void *arg) +{ + int err, event = COBALT_PTRACE_EVENT_STOP; + + pthread_setname_np(pthread_self(), "pthelper"); + + err = sem_wait(&kickoff_helper); + check_no_error("sem_wait", err); + + err = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + check_no_error("pthread_setcanceltype", err); + + err = cobalt_ptrace_helper_init(); + check_no_error("cobalt_ptrace_helper_init", err); + + while (1) { + err = cobalt_ptrace_event_wait(event); + check_no_error("cobalt_ptrace_event_wait", err); + + if (event == COBALT_PTRACE_EVENT_STOP) { + stop_events++; + event = COBALT_PTRACE_EVENT_RESUME; + } else { + check("event is COBALT_PTRACE_EVENT_RESUME", + event, COBALT_PTRACE_EVENT_RESUME); + cont_events++; + event = COBALT_PTRACE_EVENT_STOP; + } + } return NULL; } @@ -223,6 +278,8 @@ static int run_gdb(struct smokey_test *t, int argc, char *const argv[]) err = sem_init(&kickoff_lo, 0, 0); check_no_error("sem_init", err); + err = sem_init(&kickoff_helper, 0, 0); + check_no_error("sem_init", err); err = pthread_attr_init(&attr); check_no_error("pthread_attr_init", err); @@ -233,6 +290,13 @@ static int run_gdb(struct smokey_test *t, int argc, char *const argv[]) err = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set), &cpu_set); check_no_error("pthread_attr_setaffinity_np", err); + params.sched_priority = 3; + err = pthread_attr_setschedparam(&attr, ¶ms); + check_no_error("pthread_attr_setschedparam", err); + err = pthread_create(&thread_ptrace_helper, &attr, + thread_ptrace_helper_func, NULL); + check_no_error("pthread_create", err); + params.sched_priority = 2; err = pthread_attr_setschedparam(&attr, ¶ms); check_no_error("pthread_attr_setschedparam", err); @@ -293,6 +357,22 @@ static int run_gdb(struct smokey_test *t, int argc, char *const argv[]) smokey_trace("synchronous continue"); eval_expression("thread_loops==expected_loops", "1"); + send_command("c\n", 1); + + smokey_trace("stop with event"); + eval_expression("thread_loops==expected_loops", "1"); + eval_expression("stop_events", "1"); + eval_expression("cont_events", "0"); + send_command("c\n", 1); + + smokey_trace("continue with event"); + eval_expression("thread_loops==expected_loops", "1"); + eval_expression("stop_events", "2"); + eval_expression("cont_events", "1"); + send_command("c\n", 1); + + smokey_trace("terminate ptrace helper"); + eval_expression("ptrace_helper_terminated", "1"); send_command("q\n", 0); pause(); -- 2.26.2
