Inform about new thread in a single place.

* thread.c (add_thread_silent): Renamed
        from add_thread.
        (print_thread_events): New variable definition.
        (show_print_thread_events): New function.
        (_initialize_thread): Add "set print thread-events" and
        "show print thread-events" commands.
        (add_thread): Announce new thread.
        * gdbthread.h (add_thread_silent): Declare.
        (print_thread_events): New variable declaration.
        * inf-ttrace.c (inf_ttrace_wait): Don't
        inform about new thread, as add_thread is always
        called too, and will take care of that.
        * infrun.c (handle_inferior_event): Likewise.
        * procfs.c (procfs_wait): Likewise.
        * remote.c (remote_currthread): Likewise.
        * sol-thread.c (sol_thread_wait): Likewise.
        * win32-nat.c (get_win32_debug_event): Likewise.
        * linux-thread-db.c (attach_thread): Likewise.
        Remove the verbose parameter.
        (check_event): Make detach_thread be verbose
        only if print_thread_events is set.
        * linux-nat.c (lin_lwp_attach_lwp): Don't inform
        about new thread.  This is called only from
        linux-thread-db.c:attach_thread, which will take care.
        Remove the verbose parameter.
        * linux-nat.h (lin_lwp_attach_lwp): Adjust prototype.
This commit is contained in:
Vladimir Prus 2008-01-23 11:26:29 +00:00
parent 73f4030dfa
commit 93815fbfa5
19 changed files with 327 additions and 62 deletions

View File

@ -1,3 +1,33 @@
2008-01-23 Vladimir Prus <vladimir@codesourcery.com>
Chris Demetriou <cgd@google.com>
* thread.c (add_thread_silent): Renamed
from add_thread.
(print_thread_events): New variable definition.
(show_print_thread_events): New function.
(_initialize_thread): Add "set print thread-events" and
"show print thread-events" commands.
(add_thread): Announce new thread.
* gdbthread.h (add_thread_silent): Declare.
(print_thread_events): New variable declaration.
* inf-ttrace.c (inf_ttrace_wait): Don't
inform about new thread, as add_thread is always
called too, and will take care of that.
* infrun.c (handle_inferior_event): Likewise.
* procfs.c (procfs_wait): Likewise.
* remote.c (remote_currthread): Likewise.
* sol-thread.c (sol_thread_wait): Likewise.
* win32-nat.c (get_win32_debug_event): Likewise.
* linux-thread-db.c (attach_thread): Likewise.
Remove the verbose parameter.
(check_event): Make detach_thread be verbose
only if print_thread_events is set.
* linux-nat.c (lin_lwp_attach_lwp): Don't inform
about new thread. This is called only from
linux-thread-db.c:attach_thread, which will take care.
Remove the verbose parameter.
* linux-nat.h (lin_lwp_attach_lwp): Adjust prototype.
2008-01-23 Nick Roberts <nickrob@snap.net.nz>
* mi/mi-cmd-var.c (mi_cmd_var_set_format): Add value field to output.

View File

@ -366,7 +366,7 @@ bsd_uthread_wait (ptid_t ptid, struct target_waitstatus *status)
if (ptid_get_tid (ptid) != 0 && !in_thread_list (ptid)
&& ptid_get_tid (inferior_ptid) == 0)
{
add_thread (ptid);
add_thread_silent (ptid);
inferior_ptid = ptid;
}

View File

@ -1,3 +1,8 @@
2008-01-23 Chris Demetriou <cgd@google.com>
* gdb.texinfo (Threads): Document new "set print thread-events"
and "show print thread-events" commands.
2008-01-19 Eli Zaretskii <eliz@gnu.org>
* gdb.texinfo (Specify Location): New section.

View File

@ -2238,6 +2238,8 @@ programs:
@item @samp{thread apply [@var{threadno}] [@var{all}] @var{args}},
a command to apply a command to a list of threads
@item thread-specific breakpoints
@item @samp{set print thread-events}, which controls printing of
messages on thread start and exit.
@end itemize
@quotation
@ -2431,6 +2433,22 @@ threads that you want affected with the command argument
shown in the first field of the @samp{info threads} display; or it
could be a range of thread numbers, as in @code{2-4}. To apply a
command to all threads, type @kbd{thread apply all @var{command}}.
@kindex set print thread-events
@cindex print messages on thread start and exit
@item set print thread-events
@itemx set print thread-events on
@itemx set print thread-events off
The @code{set print thread-events} command allows you to enable or
disable printing of messages when @value{GDBN} notices that new threads have
started or that threads have exited. By default, these messages will
be printed if detection of these events is supported by the target.
Note that these messages cannot be disabled on all targets.
@kindex show print thread-events
@item show print thread-events
Show whether messages will be printed when @value{GDBN} detects that threads
have started and exited.
@end table
@cindex automatic thread selection

View File

@ -69,11 +69,16 @@ struct thread_info
/* Create an empty thread list, or empty the existing one. */
extern void init_thread_list (void);
/* Add a thread to the thread list.
Note that add_thread now returns the handle of the new thread,
so that the caller may initialize the private thread data. */
/* Add a thread to the thread list, print a message
that a new thread is found, and return the pointer to
the new thread. Caller my use this pointer to
initialize the private thread data. */
extern struct thread_info *add_thread (ptid_t ptid);
/* Same as add_thread, but does not print a message
about new thread. */
extern struct thread_info *add_thread_silent (ptid_t ptid);
/* Delete an existing thread list entry. */
extern void delete_thread (ptid_t);
@ -141,4 +146,8 @@ extern void switch_to_thread (ptid_t ptid);
/* Commands with a prefix of `thread'. */
extern struct cmd_list_element *thread_cmd_list;
/* Print notices on thread events (attach, detach, etc.), set with
`set print thread-events'. */
extern int print_thread_events;
#endif /* GDBTHREAD_H */

View File

@ -962,7 +962,6 @@ inf_ttrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
sizeof (struct inf_ttrace_private_thread_info));
inf_ttrace_num_lwps++;
}
printf_filtered (_("[New %s]\n"), target_pid_to_str (ptid));
ti = add_thread (ptid);
ti->private =
xmalloc (sizeof (struct inf_ttrace_private_thread_info));

View File

@ -1331,13 +1331,7 @@ handle_inferior_event (struct execution_control_state *ecs)
if (ecs->ws.kind != TARGET_WAITKIND_EXITED
&& ecs->ws.kind != TARGET_WAITKIND_SIGNALLED && ecs->new_thread_event)
{
add_thread (ecs->ptid);
ui_out_text (uiout, "[New ");
ui_out_text (uiout, target_pid_to_str (ecs->ptid));
ui_out_text (uiout, "]\n");
}
add_thread (ecs->ptid);
switch (ecs->ws.kind)
{

View File

@ -871,7 +871,7 @@ exit_lwp (struct lwp_info *lp)
be attached. */
int
lin_lwp_attach_lwp (ptid_t ptid, int verbose)
lin_lwp_attach_lwp (ptid_t ptid)
{
struct lwp_info *lp;
@ -956,9 +956,6 @@ lin_lwp_attach_lwp (ptid_t ptid, int verbose)
lp->stopped = 1;
}
if (verbose)
printf_filtered (_("[New %s]\n"), target_pid_to_str (ptid));
return 0;
}
@ -2090,8 +2087,6 @@ retry:
}
add_thread (lp->ptid);
printf_unfiltered (_("[New %s]\n"),
target_pid_to_str (lp->ptid));
}
/* Save the trap's siginfo in case we need it later. */

View File

@ -95,7 +95,7 @@ void linux_proc_pending_signals (int pid, sigset_t *pending, sigset_t *blocked,
/* linux-nat functions for handling fork events. */
extern void linux_enable_event_reporting (ptid_t ptid);
extern int lin_lwp_attach_lwp (ptid_t ptid, int verbose);
extern int lin_lwp_attach_lwp (ptid_t ptid);
/* Iterator function for lin-lwp's lwp list. */
struct lwp_info *iterate_over_lwps (int (*callback) (struct lwp_info *,

View File

@ -118,7 +118,7 @@ static CORE_ADDR td_death_bp_addr;
/* Prototypes for local functions. */
static void thread_db_find_new_threads (void);
static void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
const td_thrinfo_t *ti_p, int verbose);
const td_thrinfo_t *ti_p);
static void detach_thread (ptid_t ptid, int verbose);
@ -279,7 +279,7 @@ thread_get_info_callback (const td_thrhandle_t *thp, void *infop)
if (thread_info == NULL)
{
/* New thread. Attach to it now (why wait?). */
attach_thread (thread_ptid, thp, &ti, 1);
attach_thread (thread_ptid, thp, &ti);
thread_info = find_thread_pid (thread_ptid);
gdb_assert (thread_info != NULL);
}
@ -670,7 +670,7 @@ thread_db_new_objfile (struct objfile *objfile)
static void
attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
const td_thrinfo_t *ti_p, int verbose)
const td_thrinfo_t *ti_p)
{
struct thread_info *tp;
td_err_e err;
@ -702,7 +702,7 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
return; /* A zombie thread -- do not attach. */
/* Under GNU/Linux, we have to attach to each and every thread. */
if (lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid)), 0) < 0)
if (lin_lwp_attach_lwp (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid))) < 0)
return;
/* Add the thread to GDB's thread list. */
@ -710,9 +710,6 @@ attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
tp->private = xmalloc (sizeof (struct private_thread_info));
memset (tp->private, 0, sizeof (struct private_thread_info));
if (verbose)
printf_unfiltered (_("[New %s]\n"), target_pid_to_str (ptid));
/* Enable thread event reporting for this thread. */
err = td_thr_event_enable_p (th_p, 1);
if (err != TD_OK)
@ -843,7 +840,7 @@ check_event (ptid_t ptid)
case TD_CREATE:
/* Call attach_thread whether or not we already know about a
thread with this thread ID. */
attach_thread (ptid, msg.th_p, &ti, 1);
attach_thread (ptid, msg.th_p, &ti);
break;
@ -852,7 +849,7 @@ check_event (ptid_t ptid)
if (!in_thread_list (ptid))
error (_("Spurious thread death event."));
detach_thread (ptid, 1);
detach_thread (ptid, print_thread_events);
break;
@ -976,7 +973,7 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
}
if (!in_thread_list (ptid))
attach_thread (ptid, th_p, &ti, 1);
attach_thread (ptid, th_p, &ti);
return 0;
}

View File

@ -4119,11 +4119,8 @@ wait_again:
temp_ptid = MERGEPID (pi->pid, temp_tid);
/* If not in GDB's thread list, add it. */
if (!in_thread_list (temp_ptid))
{
printf_filtered (_("[New %s]\n"),
target_pid_to_str (temp_ptid));
add_thread (temp_ptid);
}
add_thread (temp_ptid);
/* Return to WFI, but tell it to immediately resume. */
status->kind = TARGET_WAITKIND_SPURIOUS;
return inferior_ptid;
@ -4189,11 +4186,7 @@ wait_again:
/* If not in GDB's thread list, add it. */
temp_ptid = MERGEPID (pi->pid, temp_tid);
if (!in_thread_list (temp_ptid))
{
printf_filtered (_("[New %s]\n"),
target_pid_to_str (temp_ptid));
add_thread (temp_ptid);
}
add_thread (temp_ptid);
status->kind = TARGET_WAITKIND_STOPPED;
status->value.sig = 0;
@ -4280,7 +4273,6 @@ wait_again:
* If we don't create a procinfo, resume may be unhappy
* later.
*/
printf_filtered (_("[New %s]\n"), target_pid_to_str (retval));
add_thread (retval);
if (find_procinfo (PIDGET (retval), TIDGET (retval)) == NULL)
create_procinfo (PIDGET (retval), TIDGET (retval));

View File

@ -1049,12 +1049,7 @@ record_currthread (int currthread)
/* If this is a new thread, add it to GDB's thread list.
If we leave it up to WFI to do this, bad things will happen. */
if (!in_thread_list (pid_to_ptid (currthread)))
{
add_thread (pid_to_ptid (currthread));
ui_out_text (uiout, "[New ");
ui_out_text (uiout, target_pid_to_str (pid_to_ptid (currthread)));
ui_out_text (uiout, "]\n");
}
add_thread (pid_to_ptid (currthread));
}
static char *last_pass_packet;

View File

@ -461,10 +461,7 @@ sol_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
if (is_thread (rtnval)
&& !ptid_equal (rtnval, save_ptid)
&& !in_thread_list (rtnval))
{
printf_filtered ("[New %s]\n", target_pid_to_str (rtnval));
add_thread (rtnval);
}
add_thread (rtnval);
}
/* During process initialization, we may get here without the thread

View File

@ -1,3 +1,8 @@
2008-01-23 Chris Demetriou <cgd@google.com>
* gdb.threads/thread_events.c: New testcase source file.
* gdb.threads/thread_events.exp: New testcase expect file.
2008-01-23 Nick Roberts <nickrob@snap.net.nz>
* lib/gdb.exp: Add the variable octal.

View File

@ -0,0 +1,55 @@
/* Copyright (C) 2007 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/>.
This file was written by Chris Demetriou (cgd@google.com). */
/* Simple test to trigger thread events (thread start, thread exit). */
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
static void *
threadfunc (void *arg)
{
printf ("in threadfunc\n");
return NULL;
}
static void
after_join_func (void)
{
printf ("finished\n");
}
int main (int argc, char *argv[])
{
pthread_t thread;
if (pthread_create (&thread, NULL, threadfunc, NULL) != 0)
{
printf ("pthread_create failed\n");
exit (1);
}
if (pthread_join (thread, NULL) != 0)
{
printf ("pthread_join failed\n");
exit (1);
}
after_join_func ();
return 0;
}

View File

@ -0,0 +1,155 @@
# Copyright (C) 2007 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@prep.ai.mit.edu
# This file was written by Chris Demetriou (cgd@google.com).
# It tests printing of thread event (start, exit) information, and
# disabling of those messages.
#
# Note: the format of thread event messages (and also whether or not
# messages are printed and can be disabled) is dependent on the target
# thread support code.
# This test has only been verified with Linux targets, and would need
# to be generalized to support other targets
if ![istarget *-*-linux*] then {
return
}
# When using gdbserver, even on Linux, we don't get notifications
# about new threads. This is expected, so don't test for that.
if [is_remote target] then {
return
}
if $tracelevel then {
strace $tracelevel
}
set prms_id 0
set bug_id 0
set testfile "thread_events"
set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } {
return -1
}
proc gdb_test_thread_start {messages_enabled command pattern message} {
global gdb_prompt
if { $messages_enabled } {
set events_expected 1
} else {
set events_expected 0
}
set events_seen 0
return [gdb_test_multiple $command $message {
-re "\\\[New Thread \[^\]\]*\\\]\r\n" {
incr events_seen;
exp_continue;
}
-re "\[\r\n\]*($pattern)\[\r\n\]+$gdb_prompt $" {
if { $events_seen != $events_expected } {
fail "$message (saw $events_seen, expected $events_expected)"
} else {
pass "$message"
}
}
}]
}
proc gdb_test_thread_exit {messages_enabled command pattern message} {
global gdb_prompt
if { $messages_enabled } {
set events_expected 1
} else {
set events_expected 0
}
set events_seen 0
return [gdb_test_multiple $command $message {
-re "\\\[Thread \[^\]\]* exited\\\]\r\n" {
incr events_seen
exp_continue;
}
-re "\[\r\n\]*($pattern)\[\r\n\]+$gdb_prompt $" {
if { $events_seen != $events_expected } {
fail "$message (saw $events_seen, expected $events_expected)"
} else {
pass "$message"
}
}
}]
}
proc test_thread_messages {enabled} {
global srcdir subdir binfile srcfile
if { $enabled } {
set enabled_string "with messages enabled"
} else {
set enabled_string "with messages disabled"
}
gdb_start
gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
if { $enabled } {
gdb_test "set print thread-events on"
} else {
gdb_test "set print thread-events off"
}
# The initial thread may log a 'New Thread' message, but we don't
# check for it.
if ![runto_main] then {
fail "Can't run to main $enabled_string"
return 1
}
gdb_test "break threadfunc" \
"Breakpoint.*at.* file .*$srcfile, line.*" \
"breakpoint at threadfunc $enabled_string"
gdb_test "break after_join_func" \
"Breakpoint.*at.* file .*$srcfile, line.*" \
"breakpoint at after_join_func $enabled_string"
# continue to threadfunc breakpoint. A thread will start.
# Expect to see a thread start message, if messages are enabled.
gdb_test_thread_start $enabled "continue" \
".*Breakpoint .*,.*threadfunc.*at.*$srcfile:.*" \
"continue to threadfunc $enabled_string"
# continue to after_join_func breakpoint. A thread will exit.
# Expect to see a thread exit message, if messages are enabled.
gdb_test_thread_exit $enabled "continue" \
".*Breakpoint .*,.*after_join_func.*at.*$srcfile:.*" \
"continue to after_join_func $enabled_string"
delete_breakpoints
gdb_exit
}
test_thread_messages 0
test_thread_messages 1

View File

@ -116,11 +116,8 @@ init_thread_list (void)
thread_list = NULL;
}
/* add_thread now returns a pointer to the new thread_info,
so that back_ends can initialize their private data. */
struct thread_info *
add_thread (ptid_t ptid)
add_thread_silent (ptid_t ptid)
{
struct thread_info *tp;
@ -133,6 +130,17 @@ add_thread (ptid_t ptid)
return tp;
}
struct thread_info *
add_thread (ptid_t ptid)
{
struct thread_info *result = add_thread_silent (ptid);
if (print_thread_events)
printf_filtered (_("[New %s]\n"), target_pid_to_str (ptid));
return result;
}
void
delete_thread (ptid_t ptid)
{
@ -675,6 +683,17 @@ thread_command (char *tidstr, int from_tty)
gdb_thread_select (uiout, tidstr, NULL);
}
/* Print notices when new threads are attached and detached. */
int print_thread_events = 1;
static void
show_print_thread_events (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
fprintf_filtered (file, _("\
Printing of thread events is %s.\n"),
value);
}
static int
do_captured_thread_select (struct ui_out *uiout, void *tidstr)
{
@ -737,4 +756,12 @@ The new thread ID must be currently known."),
if (!xdb_commands)
add_com_alias ("t", "thread", class_run, 1);
add_setshow_boolean_cmd ("thread-events", no_class,
&print_thread_events, _("\
Set printing of thread events (e.g., thread start and exit)."), _("\
Show printing of thread events (e.g., thread start and exit)."), NULL,
NULL,
show_print_thread_events,
&setprintlist, &showprintlist);
}

View File

@ -1311,10 +1311,6 @@ get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
/* Record the existence of this thread */
th = win32_add_thread (current_event.dwThreadId,
current_event.u.CreateThread.hThread);
if (info_verbose)
printf_unfiltered ("[New %s]\n",
target_pid_to_str (
pid_to_ptid (current_event.dwThreadId)));
retval = current_event.dwThreadId;
break;

View File

@ -1311,10 +1311,6 @@ get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
/* Record the existence of this thread */
th = win32_add_thread (current_event.dwThreadId,
current_event.u.CreateThread.hThread);
if (info_verbose)
printf_unfiltered ("[New %s]\n",
target_pid_to_str (
pid_to_ptid (current_event.dwThreadId)));
retval = current_event.dwThreadId;
break;