Add thread-exit annotation.

gdb/ChangeLog
2019-04-26  Amos Bird  <amosbird@gmail.com>

	* annotate.c (annotate_thread_exited): Add "thread-exited"
	annotation.

gdb/doc/ChangeLog
2019-06-06  Amos Bird  <amosbird@gmail.com>

	* annotate.texinfo (Multi-threaded Apps): Add entry for thread-exited
	annotation.

gdb/testsuite/ChangeLog
2019-06-06  Amos Bird  <amosbird@gmail.com>

	* gdb.base/annota1.exp (thread_switch): Add test for
	thread-exited annotation.
This commit is contained in:
Amos Bird
2019-06-07 01:10:14 +08:00
committed by Tom Tromey
parent dd455cf51d
commit 1a3da2cd61
9 changed files with 70 additions and 7 deletions

View File

@ -1,3 +1,8 @@
2019-04-26 Amos Bird <amosbird@gmail.com>
* annotate.c (annotate_thread_exited): Add "thread-exited"
annotation.
2019-06-06 Tom Tromey <tromey@adacore.com> 2019-06-06 Tom Tromey <tromey@adacore.com>
* maint.h (class scoped_command_stats): Use * maint.h (class scoped_command_stats): Use

View File

@ -3,6 +3,8 @@
*** Changes since GDB 8.3 *** Changes since GDB 8.3
* 'thread-exited' event is now available in the annotations interface.
* New built-in convenience variables $_gdb_major and $_gdb_minor * New built-in convenience variables $_gdb_major and $_gdb_minor
provide the GDB version. They are handy for conditionally using provide the GDB version. They are handy for conditionally using
features available only in or since specific GDB versions, in features available only in or since specific GDB versions, in

View File

@ -241,6 +241,19 @@ annotate_thread_changed (void)
} }
} }
/* Emit notification on thread exit. */
static void
annotate_thread_exited (struct thread_info *t, int silent)
{
if (annotation_level > 1)
{
printf_filtered(("\n\032\032thread-exited,"
"id=\"%d\",group-id=\"i%d\"\n"),
t->global_num, t->inf->num);
}
}
void void
annotate_field_begin (struct type *type) annotate_field_begin (struct type *type)
{ {
@ -595,4 +608,5 @@ _initialize_annotate (void)
gdb::observers::breakpoint_created.attach (breakpoint_changed); gdb::observers::breakpoint_created.attach (breakpoint_changed);
gdb::observers::breakpoint_deleted.attach (breakpoint_changed); gdb::observers::breakpoint_deleted.attach (breakpoint_changed);
gdb::observers::breakpoint_modified.attach (breakpoint_changed); gdb::observers::breakpoint_modified.attach (breakpoint_changed);
gdb::observers::thread_exit.attach (annotate_thread_exited);
} }

View File

@ -1,3 +1,8 @@
2019-06-06 Amos Bird <amosbird@gmail.com>
* annotate.texinfo (Multi-threaded Apps): Add entry for thread-exited
annotation.
2019-06-04 Christian Biesinger <cbiesinger@google.com> 2019-06-04 Christian Biesinger <cbiesinger@google.com>
* python.texi: Document new gdb.Type.objfile property. * python.texi: Document new gdb.Type.objfile property.

View File

@ -836,6 +836,13 @@ The selected thread has changed. This may occur at the request of the
user with the @code{thread} command, or as a result of execution, user with the @code{thread} command, or as a result of execution,
e.g., another thread hits a breakpoint. e.g., another thread hits a breakpoint.
@findex thread-exited@r{, annotation}
@item ^Z^Zthread-exited,id="@var{id}",group-id="@var{gid}"
This annotation is issued once for each thread that exits. The @var{id}
field contains the global @value{GDBN} identifier of the thread. The
@var{gid} field identifies the thread group this thread belongs to.
@end table @end table
@node GNU Free Documentation License @node GNU Free Documentation License

View File

@ -1,3 +1,8 @@
2019-06-06 Amos Bird <amosbird@gmail.com>
* gdb.base/annota1.exp (thread_switch): Add test for
thread-exited annotation.
2019-06-06 Tom Tromey <tromey@adacore.com> 2019-06-06 Tom Tromey <tromey@adacore.com>
* gdb.base/maint.exp: Expect command started/finished output. * gdb.base/maint.exp: Expect command started/finished output.

View File

@ -428,7 +428,7 @@ if [target_info exists gdb,nosignals] {
unsupported "signal sent" unsupported "signal sent"
} else { } else {
gdb_test_multiple "signal SIGTRAP" "signal sent" { gdb_test_multiple "signal SIGTRAP" "signal sent" {
-re ".*\032\032post-prompt\r\nContinuing with signal SIGTRAP.\r\n\r\n\032\032starting\(\r\n\r\n\032\032frames-invalid\)+\r\n\r\n\032\032signalled\r\n\r\nProgram terminated with signal \r\n\032\032signal-name\r\nSIGTRAP\r\n\032\032signal-name-end\r\n, \r\n\032\032signal-string\r\nTrace.breakpoint trap\r\n\032\032signal-string-end\r\n.\r\nThe program no longer exists.\r\n\r\n\032\032stopped\r\n$gdb_prompt$" { -re ".*\032\032post-prompt\r\nContinuing with signal SIGTRAP.\r\n\r\n\032\032starting\(\r\n\r\n\032\032frames-invalid\)+\r\n\r\n\032\032signalled\r\n\r\nProgram terminated with signal \r\n\032\032signal-name\r\nSIGTRAP\r\n\032\032signal-name-end\r\n, \r\n\032\032signal-string\r\nTrace.breakpoint trap\r\n\032\032signal-string-end\r\n.\r\nThe program no longer exists.\r\n\r\n\032\032thread-exited,id=\"${decimal}\",group-id=\"i${decimal}\"\r\n\r\n\032\032stopped\r\n$gdb_prompt$" {
pass "signal sent" pass "signal sent"
} }
} }
@ -450,6 +450,7 @@ if { [remote_file host exists core] } {
proc thread_test {} { proc thread_test {} {
global subdir srcdir testfile srcfile binfile global subdir srcdir testfile srcfile binfile
global gdb_prompt old_gdb_prompt global gdb_prompt old_gdb_prompt
global decimal
set srcfile watch_thread_num.c set srcfile watch_thread_num.c
set binfile [standard_output_file ${testfile}-watch_thread_num] set binfile [standard_output_file ${testfile}-watch_thread_num]
set gdb_prompt $old_gdb_prompt set gdb_prompt $old_gdb_prompt
@ -468,6 +469,9 @@ proc thread_test {} {
set linenum [gdb_get_line_number "all threads started"] set linenum [gdb_get_line_number "all threads started"]
gdb_breakpoint "$linenum" gdb_breakpoint "$linenum"
set linenum [gdb_get_line_number "first child thread exited"]
gdb_breakpoint "$linenum"
set gdb_prompt \ set gdb_prompt \
"\r\n\032\032pre-prompt\r\n$gdb_prompt \r\n\032\032prompt\r\n" "\r\n\032\032pre-prompt\r\n$gdb_prompt \r\n\032\032prompt\r\n"
@ -481,6 +485,12 @@ proc thread_test {} {
pass "new thread" pass "new thread"
} }
} }
gdb_test_multiple "continue" "thread exit" {
-re "\032\032thread-exited,id=\"${decimal}\",group-id=\"i${decimal}\".*\r\n$gdb_prompt$" {
pass "thread exit"
}
}
} }
} }

View File

@ -29,6 +29,8 @@ void *thread_function (void *arg); /* Pointer to function executed by each threa
static pthread_barrier_t threads_started_barrier; static pthread_barrier_t threads_started_barrier;
static pthread_barrier_t threads_started_barrier2;
#define NUM 15 #define NUM 15
static int num_threads = NUM; static int num_threads = NUM;
@ -43,6 +45,8 @@ int main () {
pthread_barrier_init (&threads_started_barrier, NULL, NUM + 1); pthread_barrier_init (&threads_started_barrier, NULL, NUM + 1);
pthread_barrier_init (&threads_started_barrier2, NULL, 2);
for (i = 0; i < NUM; i++) for (i = 0; i < NUM; i++)
{ {
res = pthread_create (&threads[i], res = pthread_create (&threads[i],
@ -53,7 +57,11 @@ int main () {
pthread_barrier_wait (&threads_started_barrier); pthread_barrier_wait (&threads_started_barrier);
sleep (180); /* all threads started */ pthread_barrier_wait (&threads_started_barrier2); /* all threads started */
pthread_join (threads[0], NULL);
sleep (180); /* first child thread exited */
exit (EXIT_SUCCESS); exit (EXIT_SUCCESS);
} }
@ -68,13 +76,18 @@ void *thread_function (void *arg) {
pthread_barrier_wait (&threads_started_barrier); pthread_barrier_wait (&threads_started_barrier);
/* Don't run forever. Run just short of it :) */ if (my_number > 0)
while (shared_var > 0)
{ {
shared_var++; /* Don't run forever. Run just short of it :) */
usleep (1); /* Loop increment. */ while (shared_var > 0)
loop (); {
shared_var++;
usleep (1); /* Loop increment. */
loop ();
}
} }
else
pthread_barrier_wait (&threads_started_barrier2);
pthread_exit (NULL); pthread_exit (NULL);
} }

View File

@ -138,6 +138,8 @@ set pat [multi_line "" \
"\032\032exited 0" \ "\032\032exited 0" \
"$inferior_exited_re normally." \ "$inferior_exited_re normally." \
"" \ "" \
"\032\032thread-exited,id=\"1\",group-id=\"i1\"" \
"" \
"\032\032stopped" \ "\032\032stopped" \
$gdb_prompt$] $gdb_prompt$]
gdb_test_multiple "continue" "continue until exit" { gdb_test_multiple "continue" "continue until exit" {