From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 105053 invoked by alias); 23 Jul 2017 21:17:38 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 105032 invoked by uid 89); 23 Jul 2017 21:17:36 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.8 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.2 spammy=bug-gdb@gnu.org, U*bug-gdb, buggdbgnuorg X-HELO: smtp.polymtl.ca Received: from smtp.polymtl.ca (HELO smtp.polymtl.ca) (132.207.4.11) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 23 Jul 2017 21:17:34 +0000 Received: from simark.ca (simark.ca [158.69.221.121]) (authenticated bits=0) by smtp.polymtl.ca (8.14.7/8.14.7) with ESMTP id v6NLHSGl002081 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Sun, 23 Jul 2017 17:17:32 -0400 Received: by simark.ca (Postfix, from userid 112) id EE6681E5E6; Sun, 23 Jul 2017 17:17:27 -0400 (EDT) Received: from simark.ca (localhost [127.0.0.1]) by simark.ca (Postfix) with ESMTP id 1E0CB1E009; Sun, 23 Jul 2017 17:17:26 -0400 (EDT) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit Date: Sun, 23 Jul 2017 21:17:00 -0000 From: Simon Marchi To: Kevin Buettner Cc: gdb-patches@sourceware.org Subject: Re: [PATCH v3 4/7] Test case for Inferior.thread_from_thread_handle In-Reply-To: <20170718175515.252308db@pinnacle.lan> References: <20170718174156.5da204b0@pinnacle.lan> <20170718175515.252308db@pinnacle.lan> Message-ID: X-Sender: simon.marchi@polymtl.ca User-Agent: Roundcube Webmail/1.3.0 X-Poly-FromMTA: (simark.ca [158.69.221.121]) at Sun, 23 Jul 2017 21:17:28 +0000 X-IsSubscribed: yes X-SW-Source: 2017-07/txt/msg00345.txt.bz2 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 > . */ > + > +#include > +#include > +#include > + > +#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 > . > + > +# 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