public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Simon Marchi <simon.marchi@polymtl.ca>
To: Kevin Buettner <kevinb@redhat.com>
Cc: gdb-patches@sourceware.org
Subject: Re: [PATCH v3 4/7] Test case for Inferior.thread_from_thread_handle
Date: Sun, 23 Jul 2017 21:17:00 -0000	[thread overview]
Message-ID: <d7965059550cb0bce99354ecec158b55@polymtl.ca> (raw)
In-Reply-To: <20170718175515.252308db@pinnacle.lan>

Hi Kevin,

On 2017-07-19 02:55, Kevin Buettner wrote:
> As the title says, this is a test case for
> Inferior.thread_from_thread_handle, a python method which will,
> given a thread library dependent thread handle, find the GDB thread
> which corresponds to that thread handle (in the inferior under
> consideration).
> 
> The C file for this test case causes the thread handles for the
> main thread and two child threads to be placed into an array.  The
> test case runs to one of the functions (do_something()) at which point,
> it retrieves the thread handles from the array and attempts to find the
> correponding thread in GDB's internal thread list.

"correponding"

> 
> I use barriers to make sure that both threads have actually started;
> execution will stop when one of the threads breaks at do_something.
> 
> Thanks to Simon Marchi for suggestions for forcing the thread
> numbering to be stable.
> 
> gdb/testsuite/ChangeLog:
> 
>     	* gdb.python/py-thrhandle.c, gdb.python/py-thrhandle.exp: New
>     	files.
> ---
>  gdb/testsuite/gdb.python/py-thrhandle.c   | 97 
> +++++++++++++++++++++++++++++++
>  gdb/testsuite/gdb.python/py-thrhandle.exp | 72 +++++++++++++++++++++++
>  2 files changed, 169 insertions(+)
> 
> diff --git a/gdb/testsuite/gdb.python/py-thrhandle.c
> b/gdb/testsuite/gdb.python/py-thrhandle.c
> new file mode 100644
> index 0000000..10e0222
> --- /dev/null
> +++ b/gdb/testsuite/gdb.python/py-thrhandle.c
> @@ -0,0 +1,97 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2017 Free Software Foundation, Inc.
> +
> +   This program is free software; you can redistribute it and/or 
> modify
> +   it under the terms of the GNU General Public License as published 
> by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program 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 General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see  
> <http://www.gnu.org/licenses/>.  */
> +
> +#include <pthread.h>
> +#include <unistd.h>
> +#include <memory.h>
> +
> +#define NTHR 3
> +#define NBOGUSTHR 2
> +
> +int thr_data[NTHR];
> +
> +/* Thread handles for each thread plus some "bogus" threads.  */
> +pthread_t thrs[NTHR + NBOGUSTHR];
> +
> +/* The thread children will meet at this barrier. */
> +pthread_barrier_t c_barrier;
> +
> +/* The main thread and child thread will meet at this barrier. */
> +pthread_barrier_t mc_barrier;
> +
> +void
> +do_something (int n)
> +{
> +}
> +
> +void *
> +do_work (void *data)
> +{
> +  int num = * (int *) data;
> +
> +  /* As the child threads are created, they'll meet the main thread
> +     at this barrier.  We do this to ensure that threads end up in
> +     GDB's thread list in the order in which they were created.  
> Having
> +     this ordering makes it easier to write the test.  */
> +  pthread_barrier_wait (&mc_barrier);
> +
> +  /* All of the child threads will meet at this barrier before 
> proceeding.
> +     This ensures that all threads will be active (not exited) and in
> +     roughly the same state when the first one hits the breakpoint in
> +     do_something().  */
> +  pthread_barrier_wait (&c_barrier);
> +
> +  do_something (num);
> +
> +  pthread_exit (NULL);
> +}
> +
> +void
> +after_mc_barrier (void)
> +{
> +}
> +
> +int
> +main (int argc, char **argv)
> +{
> +  int i;
> +
> +  pthread_barrier_init (&c_barrier, NULL, NTHR - 1);
> +
> +  thrs[0] = pthread_self ();
> +  thr_data[0] = 1;
> +
> +  /* Create two bogus thread handles.  */
> +  memset (&thrs[NTHR], 0, sizeof (pthread_t));
> +  memset (&thrs[NTHR + 1], 0xaa, sizeof (pthread_t));
> +
> +  for (i = 1; i < NTHR; i++)
> +    {
> +      thr_data[i] = i + 1;
> +
> +      pthread_barrier_init (&mc_barrier, NULL, 2);

I don't think it's wrong to init/destroy the barrier repeatedly, but 
it's not necessary.  After the barrier has "opened", it is reset with 
the count it was initialized with.  So you can just call _wait again on 
it.

> +
> +      pthread_create (&thrs[i], NULL, do_work, &thr_data[i]);
> +
> +      pthread_barrier_wait (&mc_barrier);
> +      pthread_barrier_destroy (&mc_barrier);
> +      after_mc_barrier ();
> +    }
> +
> +  for (i = 1; i < NTHR; i++)
> +    pthread_join (thrs[i], NULL);
> +}
> diff --git a/gdb/testsuite/gdb.python/py-thrhandle.exp
> b/gdb/testsuite/gdb.python/py-thrhandle.exp
> new file mode 100644
> index 0000000..033737d
> --- /dev/null
> +++ b/gdb/testsuite/gdb.python/py-thrhandle.exp
> @@ -0,0 +1,72 @@
> +# Copyright (C) 2017 Free Software Foundation, Inc.
> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program 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 General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see 
> <http://www.gnu.org/licenses/>.
> +
> +# Please email any bugs, comments, and/or additions to this file to:
> +# bug-gdb@gnu.org
> +
> +# This file verifies that gdb.thread_from_thread_handle works as 
> expected.

This is now gdb.Inferior.thread_from_thread_handle.

> +
> +standard_testfile
> +
> +
> +if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}"
> "${binfile}" executable debug] != "" } {
> +    return -1
> +}
> +
> +clean_restart ${binfile}
> +runto_main
> +
> +gdb_test "break after_mc_barrier" \
> +    "Breakpoint 2 at .*: file .*${srcfile}, line .*" \
> +         "breakpoint on after_mc_barrier"
> +
> +gdb_test "break do_something" \
> +    "Breakpoint 3 at .*: file .*${srcfile}, line .*" \
> +         "breakpoint on do_something"
> +
> +gdb_test "continue" \
> +	"Breakpoint 2, after_mc_barrier .*" \
> +	"run to after_mc_barrier (1)"

Do not use parentheses at the end of the test name:
https://sourceware.org/gdb/wiki/GDBTestcaseCookbook#Do_not_use_.22tail_parentheses.22_on_test_messages

Alternatively, you can use gdb_continue_to_breakpoint or gdb_continue 
(not sure why we have both).

> +
> +gdb_test_no_output "del 2" "delete after_mc_barrier breakpoint"
> +
> +gdb_test "continue" \
> +	"Breakpoint 3, do_something .*" \
> +	"run to do_something"
> +
> +# The current thread, indicated by '*' in the "info threads" output
> +# should be stopped in do_something() with a value of n which is the
> +# same as the number reported in the "Id" column.  If it's not, then
> +# something went wrong with the start up sequence which should cause
> +# the main thread to be thread 1, the first child thread to be thread
> +# 2, and the second child thread to be thread 3.
> +
> +gdb_test "info threads"  \
> +	{.*[\r\n]+\* +([0-9]+) +Thread[^\r\n]* do_something \(n=\1\) at.*}

I didn't understand the comment when reading it at first, then wondered 
for way too long how we could end up with n=1 :).

> +gdb_test "python print
> gdb.selected_inferior().thread_from_thread_handle(gdb.parse_and_eval('thrs\[0\]')).num"
> \
> +	"1"
> +
> +gdb_test "python print
> gdb.selected_inferior().thread_from_thread_handle(gdb.parse_and_eval('thrs\[1\]')).num"
> \
> +	"2"
> +
> +gdb_test "python print
> gdb.selected_inferior().thread_from_thread_handle(gdb.parse_and_eval('thrs\[2\]')).num"
> \
> +	"3"
> +
> +gdb_test "python print
> gdb.selected_inferior().thread_from_thread_handle(gdb.parse_and_eval('thrs\[3\]'))"
> \
> +	"None"
> +
> +gdb_test "python print
> gdb.selected_inferior().thread_from_thread_handle(gdb.parse_and_eval('thrs\[4\]'))"
> \
> +	"None"

Please use parentheses with print, so it works with Python 3.  But then, 
your test name will have tail parentheses, so it might be a good idea to 
give them explicit names.

Thanks,

Simon

  reply	other threads:[~2017-07-23 21:17 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-19  0:42 [PATCH v3 0/7] Thread handle to thread info mapping Kevin Buettner
2017-07-19  0:54 ` [PATCH v3 1/7] Add target method for converting thread handle to thread_info struct pointer Kevin Buettner
2017-07-23 20:39   ` Simon Marchi
2017-07-19  0:54 ` [PATCH v3 2/7] Add `thread_from_thread_handle' method to (Python) gdb.Inferior Kevin Buettner
2017-07-23 20:53   ` Simon Marchi
2017-07-19  0:55 ` [PATCH v3 5/7] Add thread_db_notice_clone to gdbserver Kevin Buettner
2017-07-23 21:27   ` Simon Marchi
2017-07-19  0:55 ` [PATCH v3 3/7] Documentation for Inferior.thread_from_thread_handle Kevin Buettner
2017-07-19  2:33   ` Eli Zaretskii
2017-07-19  0:55 ` [PATCH v3 4/7] Test case " Kevin Buettner
2017-07-23 21:17   ` Simon Marchi [this message]
2017-07-19  0:56 ` [PATCH v3 6/7] Add thread_handle_to_thread_info support for remote targets Kevin Buettner
2017-07-23 21:47   ` Simon Marchi
2017-07-19  0:56 ` [PATCH v3 7/7] Documentation for qXfer:threads:read handle attribute Kevin Buettner
2017-07-19  2:34   ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d7965059550cb0bce99354ecec158b55@polymtl.ca \
    --to=simon.marchi@polymtl.ca \
    --cc=gdb-patches@sourceware.org \
    --cc=kevinb@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).