From patchwork Wed Apr 19 16:18:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 20095 Received: (qmail 79436 invoked by alias); 19 Apr 2017 16:18:16 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 79368 invoked by uid 89); 19 Apr 2017 16:18:15 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_STOCKGEN, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 19 Apr 2017 16:18:08 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 737BE80494 for ; Wed, 19 Apr 2017 16:18:09 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 737BE80494 Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=palves@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 737BE80494 Received: from cascais.lan (ovpn04.gateway.prod.ext.phx2.redhat.com [10.5.9.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id 560837F361 for ; Wed, 19 Apr 2017 16:18:08 +0000 (UTC) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH v2] RAII-fy make_cleanup_restore_current_thread & friends Date: Wed, 19 Apr 2017 17:18:07 +0100 Message-Id: <1492618687-11704-1-git-send-email-palves@redhat.com> New in v2: - v1 had missed deleting save_current_program_space / restore_program_space. After all the make_cleanup_restore_current_thread fixing, I thought I'd convert that and its relatives (which are all cleanups) to RAII classes. scoped_restore_current_pspace_and_thread was put in a separate file to avoid a circular dependency. Tested on x86-64 Fedora 23, native and gdbserver. gdb/ChangeLog: yyyy-mm-dd Pedro Alves * Makefile.in (SFILES): Add progspace-and-thread.c. (HFILES_NO_SRCDIR): Add progspace-and-thread.h. (COMMON_OBS): Add progspace-and-thread.o. * breakpoint.c: Include "progspace-and-thread.h". (update_inserted_breakpoint_locations) (insert_breakpoint_locations, create_longjmp_master_breakpoint): Use scoped_restore_current_pspace_and_thread. (create_std_terminate_master_breakpoint): Use scoped_restore_current_program_space. (remove_breakpoint): Use scoped_restore_current_pspace_and_thread. (print_breakpoint_location): Use scoped_restore_current_program_space. (bp_loc_is_permanent): Use scoped_restore_current_pspace_and_thread. (resolve_sal_pc): Use scoped_restore_current_pspace_and_thread. (download_tracepoint_locations): Use scoped_restore_current_pspace_and_thread. (breakpoint_re_set): Use scoped_restore_current_pspace_and_thread. * exec.c (exec_close_1): Use scoped_restore_current_program_space. (enum step_over_calls_kind): Moved from inferior.h. (class scoped_restore_current_thread): New class. * gdbthread.h (make_cleanup_restore_current_thread): Delete declaration. (scoped_restore_current_thread): New class. * infcmd.c: Include "common/gdb_optional.h". (continue_1, proceed_after_attach): Use scoped_restore_current_thread. (notice_new_inferior): Use scoped_restore_current_thread. * inferior.c: Include "progspace-and-thread.h". (restore_inferior, save_current_inferior): Delete. (add_inferior_command, clone_inferior_command): Use scoped_restore_current_pspace_and_thread. * inferior.h (scoped_restore_current_inferior): New class. * infrun.c: Include "progspace-and-thread.h" and "common/gdb_optional.h". (follow_fork_inferior): Use scoped_restore_current_pspace_and_thread. (scoped_restore_exited_inferior): New class. (handle_vfork_child_exec_or_exit): Use scoped_restore_exited_inferior, scoped_restore_current_pspace_and_thread, scoped_restore_current_thread and scoped_restore. (fetch_inferior_event): Use scoped_restore_current_thread. * linespec.c (decode_line_full, decode_line_1): Use scoped_restore_current_program_space. * mi/mi-main.c: Include "progspace-and-thread.h". (exec_continue): Use scoped_restore_current_thread. (mi_cmd_exec_run): Use scoped_restore_current_pspace_and_thread. (mi_cmd_trace_frame_collected): Use scoped_restore_current_thread. * proc-service.c (ps_pglobal_lookup): Use scoped_restore_current_program_space. * progspace-and-thread.c: New file. * progspace-and-thread.h: New file. * progspace.c (release_program_space, clone_program_space): Use scoped_restore_current_program_space. (restore_program_space, save_current_program_space) (save_current_space_and_thread): Delete. (switch_to_program_space_and_thread): Moved to progspace-and-thread.c. * progspace.h (save_current_program_space) (save_current_space_and_thread): Delete declarations. (scoped_restore_current_program_space): New class. * remote.c (remote_btrace_maybe_reopen): Use scoped_restore_current_thread. * symtab.c: Include "progspace-and-thread.h". (skip_prologue_sal): Use scoped_restore_current_pspace_and_thread. * thread.c (print_thread_info_1): Use scoped_restore_current_thread. (struct current_thread_cleanup): Delete. (do_restore_current_thread_cleanup) (restore_current_thread_cleanup_dtor): Rename/convert both to ... (scoped_restore_current_thread::~scoped_restore_current_thread): ... this new dtor. (make_cleanup_restore_current_thread): Rename/convert to ... (scoped_restore_current_thread::scoped_restore_current_thread): ... this new ctor. (thread_apply_all_command): Use scoped_restore_current_thread. (thread_apply_command): Use scoped_restore_current_thread. * tracepoint.c (tdump_command): Use scoped_restore_current_thread. * varobj.c (value_of_root_1): Use scoped_restore_current_thread. --- gdb/Makefile.in | 3 + gdb/breakpoint.c | 97 ++++++---------- gdb/exec.c | 15 +-- gdb/gdbthread.h | 22 +++- gdb/infcmd.c | 31 ++---- gdb/inferior.c | 29 +---- gdb/inferior.h | 23 +++- gdb/infrun.c | 65 ++++++----- gdb/linespec.c | 6 +- gdb/mi/mi-main.c | 13 +-- gdb/proc-service.c | 18 +-- gdb/progspace-and-thread.c | 43 +++++++ gdb/progspace-and-thread.h | 40 +++++++ gdb/progspace.c | 80 +------------ gdb/progspace.h | 32 ++++-- gdb/remote.c | 5 +- gdb/symtab.c | 12 +- gdb/thread.c | 271 ++++++++++++++++++++------------------------- gdb/tracepoint.c | 6 +- gdb/varobj.c | 5 +- 20 files changed, 386 insertions(+), 430 deletions(-) create mode 100644 gdb/progspace-and-thread.c create mode 100644 gdb/progspace-and-thread.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in index b865b7c..3a7cd89 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1146,6 +1146,7 @@ SFILES = \ probe.c \ proc-service.list \ progspace.c \ + progspace-and-thread.c \ prologue-value.c \ psymtab.c \ record.c \ @@ -1401,6 +1402,7 @@ HFILES_NO_SRCDIR = \ proc-utils.h \ procfs.h \ progspace.h \ + progspace-and-thread.h \ prologue-value.h \ psympriv.h \ psymtab.h \ @@ -1755,6 +1757,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ printcmd.o \ probe.o \ progspace.o \ + progspace-and-thread.o \ prologue-value.o \ psymtab.o \ ptid.o \ diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 4940ec2..09d5d5c 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -80,6 +80,7 @@ #include "mi/mi-common.h" #include "extension.h" #include +#include "progspace-and-thread.h" /* Enums for exception-handling support. */ enum exception_event_kind @@ -3066,7 +3067,7 @@ update_inserted_breakpoint_locations (void) there was an error. */ tmp_error_stream.puts ("Warning:\n"); - struct cleanup *cleanups = save_current_space_and_thread (); + scoped_restore_current_pspace_and_thread restore; ALL_BP_LOCATIONS (bl, blp_tmp) { @@ -3102,8 +3103,6 @@ update_inserted_breakpoint_locations (void) target_terminal_ours_for_output (); error_stream (tmp_error_stream); } - - do_cleanups (cleanups); } /* Used when starting or continuing the program. */ @@ -3125,7 +3124,7 @@ insert_breakpoint_locations (void) there was an error. */ tmp_error_stream.puts ("Warning:\n"); - struct cleanup *cleanups = save_current_space_and_thread (); + scoped_restore_current_pspace_and_thread restore; ALL_BP_LOCATIONS (bl, blp_tmp) { @@ -3203,8 +3202,6 @@ You may have requested too many hardware breakpoints/watchpoints.\n"); target_terminal_ours_for_output (); error_stream (tmp_error_stream); } - - do_cleanups (cleanups); } /* Used when the program stops. @@ -3490,9 +3487,8 @@ static void create_longjmp_master_breakpoint (void) { struct program_space *pspace; - struct cleanup *old_chain; - old_chain = save_current_program_space (); + scoped_restore_current_program_space restore_pspace; ALL_PSPACES (pspace) { @@ -3596,8 +3592,6 @@ create_longjmp_master_breakpoint (void) } } } - - do_cleanups (old_chain); } /* Create a master std::terminate breakpoint. */ @@ -3605,10 +3599,9 @@ static void create_std_terminate_master_breakpoint (void) { struct program_space *pspace; - struct cleanup *old_chain; const char *const func_name = "std::terminate()"; - old_chain = save_current_program_space (); + scoped_restore_current_program_space restore_pspace; ALL_PSPACES (pspace) { @@ -3653,8 +3646,6 @@ create_std_terminate_master_breakpoint (void) b->enable_state = bp_disabled; } } - - do_cleanups (old_chain); } /* Install a master breakpoint on the unwinder's debug hook. */ @@ -4078,9 +4069,6 @@ remove_breakpoint_1 (struct bp_location *bl, enum remove_bp_reason reason) static int remove_breakpoint (struct bp_location *bl) { - int ret; - struct cleanup *old_chain; - /* BL is never in moribund_locations by our callers. */ gdb_assert (bl->owner != NULL); @@ -4088,14 +4076,11 @@ remove_breakpoint (struct bp_location *bl) This should not ever happen. */ gdb_assert (bl->owner->type != bp_none); - old_chain = save_current_space_and_thread (); + scoped_restore_current_pspace_and_thread restore; switch_to_program_space_and_thread (bl->pspace); - ret = remove_breakpoint_1 (bl, REMOVE_BREAKPOINT); - - do_cleanups (old_chain); - return ret; + return remove_breakpoint_1 (bl, REMOVE_BREAKPOINT); } /* Clear the "inserted" flag in all breakpoints. */ @@ -6138,7 +6123,8 @@ print_breakpoint_location (struct breakpoint *b, struct bp_location *loc) { struct ui_out *uiout = current_uiout; - struct cleanup *old_chain = save_current_program_space (); + + scoped_restore_current_program_space restore_pspace; if (loc != NULL && loc->shlib_disabled) loc = NULL; @@ -6203,8 +6189,6 @@ print_breakpoint_location (struct breakpoint *b, bp_location_condition_evaluator (loc)); uiout->text (")"); } - - do_cleanups (old_chain); } static const char * @@ -9102,9 +9086,6 @@ program_breakpoint_here_p (struct gdbarch *gdbarch, CORE_ADDR address) static int bp_loc_is_permanent (struct bp_location *loc) { - struct cleanup *cleanup; - int retval; - gdb_assert (loc != NULL); /* If we have a catchpoint or a watchpoint, just return 0. We should not @@ -9114,14 +9095,9 @@ bp_loc_is_permanent (struct bp_location *loc) if (!breakpoint_address_is_meaningful (loc->owner)) return 0; - cleanup = save_current_space_and_thread (); + scoped_restore_current_pspace_and_thread restore; switch_to_program_space_and_thread (loc->pspace); - - retval = program_breakpoint_here_p (loc->gdbarch, loc->address); - - do_cleanups (cleanup); - - return retval; + return program_breakpoint_here_p (loc->gdbarch, loc->address); } /* Build a command list for the dprintf corresponding to the current @@ -10005,16 +9981,12 @@ resolve_sal_pc (struct symtab_and_line *sal) if we have line numbers but no functions (as can happen in assembly source). */ - struct bound_minimal_symbol msym; - struct cleanup *old_chain = save_current_space_and_thread (); - + scoped_restore_current_pspace_and_thread restore; switch_to_program_space_and_thread (sal->pspace); - msym = lookup_minimal_symbol_by_pc (sal->pc); + bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (sal->pc); if (msym.minsym) sal->section = MSYMBOL_OBJ_SECTION (msym.objfile, msym.minsym); - - do_cleanups (old_chain); } } } @@ -12208,10 +12180,9 @@ static void download_tracepoint_locations (void) { struct breakpoint *b; - struct cleanup *old_chain; enum tribool can_download_tracepoint = TRIBOOL_UNKNOWN; - old_chain = save_current_space_and_thread (); + scoped_restore_current_pspace_and_thread restore; ALL_TRACEPOINTS (b) { @@ -12255,8 +12226,6 @@ download_tracepoint_locations (void) if (bp_location_downloaded) observer_notify_breakpoint_modified (b); } - - do_cleanups (old_chain); } /* Swap the insertion/duplication state between two locations. */ @@ -14541,32 +14510,32 @@ breakpoint_re_set (void) struct breakpoint *b, *b_tmp; enum language save_language; int save_input_radix; - struct cleanup *old_chain; save_language = current_language->la_language; save_input_radix = input_radix; - old_chain = save_current_space_and_thread (); - - /* Note: we must not try to insert locations until after all - breakpoints have been re-set. Otherwise, e.g., when re-setting - breakpoint 1, we'd insert the locations of breakpoint 2, which - hadn't been re-set yet, and thus may have stale locations. */ - ALL_BREAKPOINTS_SAFE (b, b_tmp) { - /* Format possible error msg. */ - char *message = xstrprintf ("Error in re-setting breakpoint %d: ", - b->number); - struct cleanup *cleanups = make_cleanup (xfree, message); - catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL); - do_cleanups (cleanups); - } - set_language (save_language); - input_radix = save_input_radix; + scoped_restore_current_pspace_and_thread restore; - jit_breakpoint_re_set (); + /* Note: we must not try to insert locations until after all + breakpoints have been re-set. Otherwise, e.g., when re-setting + breakpoint 1, we'd insert the locations of breakpoint 2, which + hadn't been re-set yet, and thus may have stale locations. */ - do_cleanups (old_chain); + ALL_BREAKPOINTS_SAFE (b, b_tmp) + { + /* Format possible error msg. */ + char *message = xstrprintf ("Error in re-setting breakpoint %d: ", + b->number); + struct cleanup *cleanups = make_cleanup (xfree, message); + catch_errors (breakpoint_re_set_one, b, message, RETURN_MASK_ALL); + do_cleanups (cleanups); + } + set_language (save_language); + input_radix = save_input_radix; + + jit_breakpoint_re_set (); + } create_overlay_event_breakpoint (); create_longjmp_master_breakpoint (); diff --git a/gdb/exec.c b/gdb/exec.c index 2c9a74b..a6f9bbb 100644 --- a/gdb/exec.c +++ b/gdb/exec.c @@ -113,17 +113,14 @@ static void exec_close_1 (struct target_ops *self) { struct program_space *ss; - struct cleanup *old_chain; + scoped_restore_current_program_space restore; - old_chain = save_current_program_space (); ALL_PSPACES (ss) - { - set_current_program_space (ss); - clear_section_table (current_target_sections); - exec_close (); - } - - do_cleanups (old_chain); + { + set_current_program_space (ss); + clear_section_table (current_target_sections); + exec_close (); + } } void diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h index 68427e9..7bf2070 100644 --- a/gdb/gdbthread.h +++ b/gdb/gdbthread.h @@ -592,7 +592,27 @@ extern int print_thread_events; extern void print_thread_info (struct ui_out *uiout, char *requested_threads, int pid); -extern struct cleanup *make_cleanup_restore_current_thread (void); +/* Save/restore current inferior/thread/frame. */ + +class scoped_restore_current_thread +{ +public: + scoped_restore_current_thread (); + ~scoped_restore_current_thread (); + + /* Disable copy. */ + scoped_restore_current_thread + (const scoped_restore_current_thread &) = delete; + void operator= + (const scoped_restore_current_thread &) = delete; + +private: + thread_info *m_thread; + inferior *m_inf; + frame_id m_selected_frame_id; + int m_selected_frame_level; + bool m_was_stopped; +}; /* Returns a pointer into the thread_info corresponding to INFERIOR_PTID. INFERIOR_PTID *must* be in the thread list. */ diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 22b2c7a..3a55e95 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -58,6 +58,7 @@ #include "thread-fsm.h" #include "top.h" #include "interps.h" +#include "common/gdb_optional.h" /* Local functions: */ @@ -730,10 +731,10 @@ continue_1 (int all_threads) { /* Don't error out if the current thread is running, because there may be other stopped threads. */ - struct cleanup *old_chain; - /* Backup current thread and selected frame. */ - old_chain = make_cleanup_restore_current_thread (); + /* Backup current thread and selected frame and restore on scope + exit. */ + scoped_restore_current_thread restore_thread; iterate_over_threads (proceed_thread_callback, NULL); @@ -754,9 +755,6 @@ continue_1 (int all_threads) */ target_terminal_inferior (); } - - /* Restore selected ptid. */ - do_cleanups (old_chain); } else { @@ -2627,15 +2625,11 @@ proceed_after_attach (int pid) { /* Don't error out if the current thread is running, because there may be other stopped threads. */ - struct cleanup *old_chain; /* Backup current thread and selected frame. */ - old_chain = make_cleanup_restore_current_thread (); + scoped_restore_current_thread restore_thread; iterate_over_threads (proceed_after_attach_callback, &pid); - - /* Restore selected ptid. */ - do_cleanups (old_chain); } /* See inferior.h. */ @@ -2922,15 +2916,13 @@ attach_command (char *args, int from_tty) void notice_new_inferior (ptid_t ptid, int leave_running, int from_tty) { - struct cleanup* old_chain; - enum attach_post_wait_mode mode; - - old_chain = make_cleanup (null_cleanup, NULL); + enum attach_post_wait_mode mode + = leave_running ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING; - mode = leave_running ? ATTACH_POST_WAIT_RESUME : ATTACH_POST_WAIT_NOTHING; + gdb::optional restore; - if (!ptid_equal (inferior_ptid, null_ptid)) - make_cleanup_restore_current_thread (); + if (inferior_ptid != null_ptid) + restore.emplace (); /* Avoid reading registers -- we haven't fetched the target description yet. */ @@ -2959,13 +2951,10 @@ notice_new_inferior (ptid_t ptid, int leave_running, int from_tty) add_inferior_continuation (attach_command_continuation, a, attach_command_continuation_free_args); - do_cleanups (old_chain); return; } attach_post_wait ("" /* args */, from_tty, mode); - - do_cleanups (old_chain); } /* diff --git a/gdb/inferior.c b/gdb/inferior.c index e85859f..5cafa6a 100644 --- a/gdb/inferior.c +++ b/gdb/inferior.c @@ -35,6 +35,7 @@ #include "arch-utils.h" #include "target-descriptions.h" #include "readline/tilde.h" +#include "progspace-and-thread.h" void _initialize_inferiors (void); @@ -72,30 +73,6 @@ set_current_inferior (struct inferior *inf) current_inferior_ = inf; } -/* A cleanups callback, helper for save_current_program_space - below. */ - -static void -restore_inferior (void *arg) -{ - struct inferior *saved_inferior = (struct inferior *) arg; - - set_current_inferior (saved_inferior); -} - -/* Save the current program space so that it may be restored by a later - call to do_cleanups. Returns the struct cleanup pointer needed for - later doing the cleanup. */ - -struct cleanup * -save_current_inferior (void) -{ - struct cleanup *old_chain = make_cleanup (restore_inferior, - current_inferior_); - - return old_chain; -} - inferior::~inferior () { inferior *inf = this; @@ -865,7 +842,7 @@ add_inferior_command (char *args, int from_tty) } } - save_current_space_and_thread (); + scoped_restore_current_pspace_and_thread restore; for (i = 0; i < copies; ++i) { @@ -945,7 +922,7 @@ clone_inferior_command (char *args, int from_tty) if (orginf == NULL) orginf = current_inferior (); - save_current_space_and_thread (); + scoped_restore_current_pspace_and_thread restore; for (i = 0; i < copies; ++i) { diff --git a/gdb/inferior.h b/gdb/inferior.h index c6fb9d3..7ee92ed 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -540,7 +540,28 @@ extern int number_of_live_inferiors (void); (not cores, not executables, real live processes). */ extern int have_live_inferiors (void); -extern struct cleanup *save_current_inferior (void); +/* Save/restore the current inferior. */ + +class scoped_restore_current_inferior +{ +public: + scoped_restore_current_inferior () + : m_saved_inf (current_inferior ()) + {} + + ~scoped_restore_current_inferior () + { set_current_inferior (m_saved_inf); } + + /* Disable copy. */ + scoped_restore_current_inferior + (const scoped_restore_current_inferior &) = delete; + void operator= + (const scoped_restore_current_inferior &) = delete; + +private: + inferior *m_saved_inf; +}; + /* Traverse all inferiors. */ diff --git a/gdb/infrun.c b/gdb/infrun.c index fcafdc1..e6db33a 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -64,6 +64,8 @@ #include "event-loop.h" #include "thread-fsm.h" #include "common/enum-flags.h" +#include "progspace-and-thread.h" +#include "common/gdb_optional.h" /* Prototypes for local functions */ @@ -487,7 +489,6 @@ holding the child stopped. Try \"set detach-on-fork\" or \ else { struct inferior *parent_inf, *child_inf; - struct cleanup *old_chain; /* Add process to GDB's tables. */ child_inf = add_inferior (ptid_get_pid (child_ptid)); @@ -498,7 +499,7 @@ holding the child stopped. Try \"set detach-on-fork\" or \ child_inf->gdbarch = parent_inf->gdbarch; copy_inferior_target_desc_info (child_inf, parent_inf); - old_chain = save_current_space_and_thread (); + scoped_restore_current_pspace_and_thread restore; inferior_ptid = child_ptid; add_thread (inferior_ptid); @@ -536,8 +537,6 @@ holding the child stopped. Try \"set detach-on-fork\" or \ required. */ solib_create_inferior_hook (0); } - - do_cleanups (old_chain); } if (has_vforked) @@ -895,6 +894,22 @@ proceed_after_vfork_done (struct thread_info *thread, return 0; } +/* Save/restore inferior_ptid, current program space and current + inferior. Only use this if the current context points at an exited + inferior (and therefore there's no current thread to save). */ +class scoped_restore_exited_inferior +{ +public: + scoped_restore_exited_inferior () + : m_saved_ptid (&inferior_ptid) + {} + +private: + scoped_restore_tmpl m_saved_ptid; + scoped_restore_current_program_space m_pspace; + scoped_restore_current_inferior m_inferior; +}; + /* Called whenever we notice an exec or exit event, to handle detaching or resuming a vfork parent. */ @@ -914,7 +929,6 @@ handle_vfork_child_exec_or_exit (int exec) if (inf->vfork_parent->pending_detach) { struct thread_info *tp; - struct cleanup *old_chain; struct program_space *pspace; struct address_space *aspace; @@ -922,16 +936,17 @@ handle_vfork_child_exec_or_exit (int exec) inf->vfork_parent->pending_detach = 0; + gdb::optional + maybe_restore_inferior; + gdb::optional + maybe_restore_thread; + + /* If we're handling a child exit, then inferior_ptid points + at the inferior's pid, not to a thread. */ if (!exec) - { - /* If we're handling a child exit, then inferior_ptid - points at the inferior's pid, not to a thread. */ - old_chain = save_inferior_ptid (); - save_current_program_space (); - save_current_inferior (); - } + maybe_restore_inferior.emplace (); else - old_chain = save_current_space_and_thread (); + maybe_restore_thread.emplace (); /* We're letting loose of the parent. */ tp = any_live_thread_of_process (inf->vfork_parent->pid); @@ -979,8 +994,6 @@ handle_vfork_child_exec_or_exit (int exec) /* Put it back. */ inf->pspace = pspace; inf->aspace = aspace; - - do_cleanups (old_chain); } else if (exec) { @@ -998,7 +1011,6 @@ handle_vfork_child_exec_or_exit (int exec) } else { - struct cleanup *old_chain; struct program_space *pspace; /* If this is a vfork child exiting, then the pspace and @@ -1010,10 +1022,11 @@ handle_vfork_child_exec_or_exit (int exec) go ahead and create a new one for this exiting inferior. */ - /* Switch to null_ptid, so that clone_program_space doesn't want - to read the selected frame of a dead process. */ - old_chain = save_inferior_ptid (); - inferior_ptid = null_ptid; + /* Switch to null_ptid while running clone_program_space, so + that clone_program_space doesn't want to read the + selected frame of a dead process. */ + scoped_restore restore_ptid + = make_scoped_restore (&inferior_ptid, null_ptid); /* This inferior is dead, so avoid giving the breakpoints module the option to write through to it (cloning a @@ -1028,10 +1041,6 @@ handle_vfork_child_exec_or_exit (int exec) inf->pspace = pspace; inf->aspace = pspace->aspace; - /* Put back inferior_ptid. We'll continue mourning this - inferior. */ - do_cleanups (old_chain); - resume_parent = inf->vfork_parent->pid; /* Break the bonds. */ inf->vfork_parent->vfork_child = NULL; @@ -1045,7 +1054,7 @@ handle_vfork_child_exec_or_exit (int exec) { /* If the user wanted the parent to be running, let it go free now. */ - struct cleanup *old_chain = make_cleanup_restore_current_thread (); + scoped_restore_current_thread restore_thread; if (debug_infrun) fprintf_unfiltered (gdb_stdlog, @@ -1053,8 +1062,6 @@ handle_vfork_child_exec_or_exit (int exec) resume_parent); iterate_over_threads (proceed_after_vfork_done, &resume_parent); - - do_cleanups (old_chain); } } } @@ -3889,12 +3896,14 @@ fetch_inferior_event (void *client_data) set_current_traceframe (-1); } + gdb::optional maybe_restore_thread; + if (non_stop) /* In non-stop mode, the user/frontend should not notice a thread switch due to internal events. Make sure we reverse to the user selected thread and frame after handling the event and running any breakpoint commands. */ - make_cleanup_restore_current_thread (); + maybe_restore_thread.emplace (); overlay_cache_invalid = 1; /* Flush target cache before starting to handle each event. Target diff --git a/gdb/linespec.c b/gdb/linespec.c index acf4900..4c076fe 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -2554,7 +2554,8 @@ decode_line_full (const struct event_location *location, int flags, search_pspace, default_symtab, default_line, canonical); cleanups = make_cleanup (linespec_parser_delete, &parser); - save_current_program_space (); + + scoped_restore_current_program_space restore_pspace; result = event_location_to_sals (&parser, location); state = PARSER_STATE (&parser); @@ -2616,7 +2617,8 @@ decode_line_1 (const struct event_location *location, int flags, search_pspace, default_symtab, default_line, NULL); cleanups = make_cleanup (linespec_parser_delete, &parser); - save_current_program_space (); + + scoped_restore_current_program_space restore_pspace; result = event_location_to_sals (&parser, location); diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index c3e7bf7..8145eb5 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -59,6 +59,7 @@ #include #include "run-time-clock.h" #include +#include "progspace-and-thread.h" enum { @@ -274,9 +275,9 @@ exec_continue (char **argv, int argc) See comment on infcmd.c:proceed_thread_callback for rationale. */ if (current_context->all || current_context->thread_group != -1) { - int pid = 0; - struct cleanup *back_to = make_cleanup_restore_current_thread (); + scoped_restore_current_thread restore_thread; + int pid = 0; if (!current_context->all) { struct inferior *inf @@ -285,7 +286,6 @@ exec_continue (char **argv, int argc) pid = inf->pid; } iterate_over_threads (proceed_thread_callback, &pid); - do_cleanups (back_to); } else { @@ -468,10 +468,9 @@ mi_cmd_exec_run (const char *command, char **argv, int argc) if (current_context->all) { - struct cleanup *back_to = save_current_space_and_thread (); + scoped_restore_current_pspace_and_thread restore; iterate_over_inferiors (run_one_inferior, &start_p); - do_cleanups (back_to); } else { @@ -2794,7 +2793,7 @@ mi_cmd_trace_frame_collected (const char *command, char **argv, int argc) /* This command only makes sense for the current frame, not the selected frame. */ - old_chain = make_cleanup_restore_current_thread (); + scoped_restore_current_thread restore_thread; select_frame (get_current_frame ()); encode_actions (tloc, &tracepoint_list, &stepping_list); @@ -2966,8 +2965,6 @@ mi_cmd_trace_frame_collected (const char *command, char **argv, int argc) do_cleanups (list_cleanup); } - - do_cleanups (old_chain); } void diff --git a/gdb/proc-service.c b/gdb/proc-service.c index 415ba0a..5e5eee0 100644 --- a/gdb/proc-service.c +++ b/gdb/proc-service.c @@ -112,25 +112,19 @@ ps_err_e ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *obj, const char *name, psaddr_t *sym_addr) { - struct bound_minimal_symbol ms; - struct cleanup *old_chain = save_current_program_space (); struct inferior *inf = find_inferior_ptid (ph->ptid); - ps_err_e result; + + scoped_restore_current_program_space restore_pspace; set_current_program_space (inf->pspace); /* FIXME: kettenis/2000-09-03: What should we do with OBJ? */ - ms = lookup_minimal_symbol (name, NULL, NULL); + bound_minimal_symbol ms = lookup_minimal_symbol (name, NULL, NULL); if (ms.minsym == NULL) - result = PS_NOSYM; - else - { - *sym_addr = core_addr_to_ps_addr (BMSYMBOL_VALUE_ADDRESS (ms)); - result = PS_OK; - } + return PS_NOSYM; - do_cleanups (old_chain); - return result; + *sym_addr = core_addr_to_ps_addr (BMSYMBOL_VALUE_ADDRESS (ms)); + return PS_OK; } /* Read SIZE bytes from the target process PH at address ADDR and copy diff --git a/gdb/progspace-and-thread.c b/gdb/progspace-and-thread.c new file mode 100644 index 0000000..a48faa0 --- /dev/null +++ b/gdb/progspace-and-thread.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2009-2017 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 "defs.h" +#include "progspace-and-thread.h" + +/* See progspace-and-thread.h */ + +void +switch_to_program_space_and_thread (program_space *pspace) +{ + inferior *inf = find_inferior_for_program_space (pspace); + + if (inf != NULL && inf->pid != 0) + { + thread_info *tp = any_live_thread_of_process (inf->pid); + + if (tp != NULL) + { + switch_to_thread (tp->ptid); + /* Switching thread switches pspace implicitly. We're + done. */ + return; + } + } + + switch_to_thread (null_ptid); + set_current_program_space (pspace); +} diff --git a/gdb/progspace-and-thread.h b/gdb/progspace-and-thread.h new file mode 100644 index 0000000..c68c79f --- /dev/null +++ b/gdb/progspace-and-thread.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2009-2017 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + + +#ifndef PROGSPACE_AND_THREAD_H +#define PROGSPACE_AND_THREAD_H + +#include "progspace.h" +#include "gdbthread.h" + +/* Save/restore the current program space, thread, inferior and frame. + Use this when you need to call + switch_to_program_space_and_thread. */ + +class scoped_restore_current_pspace_and_thread +{ + scoped_restore_current_program_space m_restore_pspace; + scoped_restore_current_thread m_restore_thread; +}; + +/* Switches full context to program space PSPACE. Switches to the + first thread found bound to PSPACE, giving preference to the + current thread, if there's one and it isn't executing. */ +void switch_to_program_space_and_thread (program_space *pspace); + +#endif diff --git a/gdb/progspace.c b/gdb/progspace.c index 4efbafe..20b6d3b 100644 --- a/gdb/progspace.c +++ b/gdb/progspace.c @@ -156,10 +156,10 @@ add_program_space (struct address_space *aspace) static void release_program_space (struct program_space *pspace) { - struct cleanup *old_chain = save_current_program_space (); - gdb_assert (pspace != current_program_space); + scoped_restore_current_program_space restore_pspace; + set_current_program_space (pspace); breakpoint_program_space_exit (pspace); @@ -173,8 +173,6 @@ release_program_space (struct program_space *pspace) /* Discard any data modules have associated with the PSPACE. */ program_space_free_data (pspace); xfree (pspace); - - do_cleanups (old_chain); } /* Copies program space SRC to DEST. Copies the main executable file, @@ -183,9 +181,7 @@ release_program_space (struct program_space *pspace) struct program_space * clone_program_space (struct program_space *dest, struct program_space *src) { - struct cleanup *old_chain; - - old_chain = save_current_program_space (); + scoped_restore_current_program_space restore_pspace; set_current_program_space (dest); @@ -195,7 +191,6 @@ clone_program_space (struct program_space *dest, struct program_space *src) if (src->symfile_object_file != NULL) symbol_file_add_main (objfile_name (src->symfile_object_file), 0); - do_cleanups (old_chain); return dest; } @@ -217,30 +212,6 @@ set_current_program_space (struct program_space *pspace) reinit_frame_cache (); } -/* A cleanups callback, helper for save_current_program_space - below. */ - -static void -restore_program_space (void *arg) -{ - struct program_space *saved_pspace = (struct program_space *) arg; - - set_current_program_space (saved_pspace); -} - -/* Save the current program space so that it may be restored by a later - call to do_cleanups. Returns the struct cleanup pointer needed for - later doing the cleanup. */ - -struct cleanup * -save_current_program_space (void) -{ - struct cleanup *old_chain = make_cleanup (restore_program_space, - current_program_space); - - return old_chain; -} - /* Returns true iff there's no inferior bound to PSPACE. */ int @@ -449,51 +420,6 @@ update_address_spaces (void) inf->aspace = inf->pspace->aspace; } -/* Save the current program space so that it may be restored by a later - call to do_cleanups. Returns the struct cleanup pointer needed for - later doing the cleanup. */ - -struct cleanup * -save_current_space_and_thread (void) -{ - struct cleanup *old_chain; - - /* If restoring to null thread, we need to restore the pspace as - well, hence, we need to save the current program space first. */ - old_chain = save_current_program_space (); - /* There's no need to save the current inferior here. - That is handled by make_cleanup_restore_current_thread. */ - make_cleanup_restore_current_thread (); - - return old_chain; -} - -/* See progspace.h */ - -void -switch_to_program_space_and_thread (struct program_space *pspace) -{ - struct inferior *inf; - - inf = find_inferior_for_program_space (pspace); - if (inf != NULL && inf->pid != 0) - { - struct thread_info *tp; - - tp = any_live_thread_of_process (inf->pid); - if (tp != NULL) - { - switch_to_thread (tp->ptid); - /* Switching thread switches pspace implicitly. We're - done. */ - return; - } - } - - switch_to_thread (null_ptid); - set_current_program_space (pspace); -} - /* See progspace.h. */ diff --git a/gdb/progspace.h b/gdb/progspace.h index 8925f56..ec1f482 100644 --- a/gdb/progspace.h +++ b/gdb/progspace.h @@ -251,11 +251,6 @@ extern int program_space_empty_p (struct program_space *pspace); extern struct program_space *clone_program_space (struct program_space *dest, struct program_space *src); -/* Save the current program space so that it may be restored by a later - call to do_cleanups. Returns the struct cleanup pointer needed for - later doing the cleanup. */ -extern struct cleanup *save_current_program_space (void); - /* Sets PSPACE as the current program space. This is usually used instead of set_current_space_and_thread when the current thread/inferior is not important for the operations that follow. @@ -266,14 +261,27 @@ extern struct cleanup *save_current_program_space (void); space. */ extern void set_current_program_space (struct program_space *pspace); -/* Saves the current thread (may be null), frame and program space in - the current cleanup chain. */ -extern struct cleanup *save_current_space_and_thread (void); +/* Save/restore the current program space. */ + +class scoped_restore_current_program_space +{ +public: + scoped_restore_current_program_space () + : m_saved_pspace (current_program_space) + {} + + ~scoped_restore_current_program_space () + { set_current_program_space (m_saved_pspace); } + + /* Disable copy. */ + scoped_restore_current_program_space + (const scoped_restore_current_program_space &) = delete; + void operator= + (const scoped_restore_current_program_space &) = delete; -/* Switches full context to program space PSPACE. Switches to the - first thread found bound to PSPACE, giving preference to the - current thread, if there's one and it isn't executing. */ -extern void switch_to_program_space_and_thread (struct program_space *pspace); +private: + program_space *m_saved_pspace; +}; /* Create a new address space object, and add it to the list. */ extern struct address_space *new_address_space (void); diff --git a/gdb/remote.c b/gdb/remote.c index 694897d..c6dc006 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -13210,12 +13210,12 @@ static void remote_btrace_maybe_reopen (void) { struct remote_state *rs = get_remote_state (); - struct cleanup *cleanup; struct thread_info *tp; int btrace_target_pushed = 0; int warned = 0; - cleanup = make_cleanup_restore_current_thread (); + scoped_restore_current_thread restore_thread; + ALL_NON_EXITED_THREADS (tp) { set_general_thread (tp->ptid); @@ -13255,7 +13255,6 @@ remote_btrace_maybe_reopen (void) tp->btrace.target->ptid = tp->ptid; tp->btrace.target->conf = rs->btrace_config; } - do_cleanups (cleanup); } /* Enable branch tracing. */ diff --git a/gdb/symtab.c b/gdb/symtab.c index 20ef76d..35a8adc 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -61,6 +61,7 @@ #include "parser-defs.h" #include "completer.h" +#include "progspace-and-thread.h" /* Forward declarations for local functions. */ @@ -3551,7 +3552,6 @@ skip_prologue_sal (struct symtab_and_line *sal) { struct symbol *sym; struct symtab_and_line start_sal; - struct cleanup *old_chain; CORE_ADDR pc, saved_pc; struct obj_section *section; const char *name; @@ -3564,7 +3564,8 @@ skip_prologue_sal (struct symtab_and_line *sal) if (sal->explicit_pc) return; - old_chain = save_current_space_and_thread (); + scoped_restore_current_pspace_and_thread restore; + switch_to_program_space_and_thread (sal->pspace); sym = find_pc_sect_function (sal->pc, sal->section); @@ -3583,10 +3584,7 @@ skip_prologue_sal (struct symtab_and_line *sal) = lookup_minimal_symbol_by_pc_section (sal->pc, sal->section); if (msymbol.minsym == NULL) - { - do_cleanups (old_chain); - return; - } + return; objfile = msymbol.objfile; pc = BMSYMBOL_VALUE_ADDRESS (msymbol); @@ -3678,8 +3676,6 @@ skip_prologue_sal (struct symtab_and_line *sal) start_sal = find_pc_sect_line (pc, section, 0); } - do_cleanups (old_chain); - /* If we're already past the prologue, leave SAL unchanged. Otherwise forward SAL to the end of the prologue. */ if (sal->pc >= pc) diff --git a/gdb/thread.c b/gdb/thread.c index e4113c2..b42b297 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -1241,7 +1241,6 @@ print_thread_info_1 (struct ui_out *uiout, char *requested_threads, { struct thread_info *tp; ptid_t current_ptid; - struct cleanup *old_chain; const char *extra_info, *name, *target_id; struct inferior *inf; int default_inf_num = current_inferior ()->num; @@ -1249,8 +1248,7 @@ print_thread_info_1 (struct ui_out *uiout, char *requested_threads, update_thread_list (); current_ptid = inferior_ptid; - /* We'll be switching threads temporarily. */ - old_chain = make_cleanup_restore_current_thread (); + struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); /* For backward compatibility, we make a list for MI. A table is preferable for the CLI, though, because it shows table @@ -1297,109 +1295,115 @@ print_thread_info_1 (struct ui_out *uiout, char *requested_threads, uiout->table_body (); } - ALL_THREADS_BY_INFERIOR (inf, tp) - { - struct cleanup *chain2; - int core; + /* We'll be switching threads temporarily. */ + { + scoped_restore_current_thread restore_thread; - if (!should_print_thread (requested_threads, default_inf_num, - global_ids, pid, tp)) - continue; + ALL_THREADS_BY_INFERIOR (inf, tp) + { + struct cleanup *chain2; + int core; - chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + if (!should_print_thread (requested_threads, default_inf_num, + global_ids, pid, tp)) + continue; - if (uiout->is_mi_like_p ()) - { - /* Compatibility. */ - if (tp->ptid == current_ptid) - uiout->text ("* "); - else - uiout->text (" "); - } - else - { - if (tp->ptid == current_ptid) - uiout->field_string ("current", "*"); - else - uiout->field_skip ("current"); - } + chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); - if (!uiout->is_mi_like_p ()) - uiout->field_string ("id-in-tg", print_thread_id (tp)); + if (uiout->is_mi_like_p ()) + { + /* Compatibility. */ + if (tp->ptid == current_ptid) + uiout->text ("* "); + else + uiout->text (" "); + } + else + { + if (tp->ptid == current_ptid) + uiout->field_string ("current", "*"); + else + uiout->field_skip ("current"); + } - if (show_global_ids || uiout->is_mi_like_p ()) - uiout->field_int ("id", tp->global_num); + if (!uiout->is_mi_like_p ()) + uiout->field_string ("id-in-tg", print_thread_id (tp)); - /* For the CLI, we stuff everything into the target-id field. - This is a gross hack to make the output come out looking - correct. The underlying problem here is that ui-out has no - way to specify that a field's space allocation should be - shared by several fields. For MI, we do the right thing - instead. */ + if (show_global_ids || uiout->is_mi_like_p ()) + uiout->field_int ("id", tp->global_num); - target_id = target_pid_to_str (tp->ptid); - extra_info = target_extra_thread_info (tp); - name = tp->name ? tp->name : target_thread_name (tp); + /* For the CLI, we stuff everything into the target-id field. + This is a gross hack to make the output come out looking + correct. The underlying problem here is that ui-out has no + way to specify that a field's space allocation should be + shared by several fields. For MI, we do the right thing + instead. */ - if (uiout->is_mi_like_p ()) - { - uiout->field_string ("target-id", target_id); - if (extra_info) - uiout->field_string ("details", extra_info); - if (name) - uiout->field_string ("name", name); - } - else - { - struct cleanup *str_cleanup; - char *contents; - - if (extra_info && name) - contents = xstrprintf ("%s \"%s\" (%s)", target_id, - name, extra_info); - else if (extra_info) - contents = xstrprintf ("%s (%s)", target_id, extra_info); - else if (name) - contents = xstrprintf ("%s \"%s\"", target_id, name); - else - contents = xstrdup (target_id); - str_cleanup = make_cleanup (xfree, contents); + target_id = target_pid_to_str (tp->ptid); + extra_info = target_extra_thread_info (tp); + name = tp->name ? tp->name : target_thread_name (tp); - uiout->field_string ("target-id", contents); - do_cleanups (str_cleanup); - } + if (uiout->is_mi_like_p ()) + { + uiout->field_string ("target-id", target_id); + if (extra_info) + uiout->field_string ("details", extra_info); + if (name) + uiout->field_string ("name", name); + } + else + { + struct cleanup *str_cleanup; + char *contents; + + if (extra_info && name) + contents = xstrprintf ("%s \"%s\" (%s)", target_id, + name, extra_info); + else if (extra_info) + contents = xstrprintf ("%s (%s)", target_id, extra_info); + else if (name) + contents = xstrprintf ("%s \"%s\"", target_id, name); + else + contents = xstrdup (target_id); + str_cleanup = make_cleanup (xfree, contents); + + uiout->field_string ("target-id", contents); + do_cleanups (str_cleanup); + } - if (tp->state == THREAD_RUNNING) - uiout->text ("(running)\n"); - else - { - /* The switch below puts us at the top of the stack (leaf - frame). */ - switch_to_thread (tp->ptid); - print_stack_frame (get_selected_frame (NULL), - /* For MI output, print frame level. */ - uiout->is_mi_like_p (), - LOCATION, 0); - } + if (tp->state == THREAD_RUNNING) + uiout->text ("(running)\n"); + else + { + /* The switch below puts us at the top of the stack (leaf + frame). */ + switch_to_thread (tp->ptid); + print_stack_frame (get_selected_frame (NULL), + /* For MI output, print frame level. */ + uiout->is_mi_like_p (), + LOCATION, 0); + } - if (uiout->is_mi_like_p ()) - { - const char *state = "stopped"; + if (uiout->is_mi_like_p ()) + { + const char *state = "stopped"; - if (tp->state == THREAD_RUNNING) - state = "running"; - uiout->field_string ("state", state); - } + if (tp->state == THREAD_RUNNING) + state = "running"; + uiout->field_string ("state", state); + } - core = target_core_of_thread (tp->ptid); - if (uiout->is_mi_like_p () && core != -1) - uiout->field_int ("core", core); + core = target_core_of_thread (tp->ptid); + if (uiout->is_mi_like_p () && core != -1) + uiout->field_int ("core", core); - do_cleanups (chain2); - } + do_cleanups (chain2); + } + + /* This end scope restores the current thread and the frame + selected before the "info threads" command. */ + } - /* Restores the current thread and the frame selected before - the "info threads" command. */ do_cleanups (old_chain); if (pid == -1 && requested_threads == NULL) @@ -1571,77 +1575,53 @@ restore_selected_frame (struct frame_id a_frame_id, int frame_level) } } -/* Data used by the cleanup installed by - 'make_cleanup_restore_current_thread'. */ - -struct current_thread_cleanup -{ - thread_info *thread; - struct frame_id selected_frame_id; - int selected_frame_level; - int was_stopped; - inferior *inf; -}; - -static void -do_restore_current_thread_cleanup (void *arg) +scoped_restore_current_thread::~scoped_restore_current_thread () { - struct current_thread_cleanup *old = (struct current_thread_cleanup *) arg; - /* If an entry of thread_info was previously selected, it won't be deleted because we've increased its refcount. The thread represented by this thread_info entry may have already exited (due to normal exit, detach, etc), so the thread_info.state is THREAD_EXITED. */ - if (old->thread != NULL + if (m_thread != NULL /* If the previously selected thread belonged to a process that has in the mean time exited (or killed, detached, etc.), then don't revert back to it, but instead simply drop back to no thread selected. */ - && old->inf->pid != 0) - switch_to_thread (old->thread); + && m_inf->pid != 0) + switch_to_thread (m_thread); else { switch_to_no_thread (); - set_current_inferior (old->inf); + set_current_inferior (m_inf); } /* The running state of the originally selected thread may have changed, so we have to recheck it here. */ if (inferior_ptid != null_ptid - && old->was_stopped + && m_was_stopped && is_stopped (inferior_ptid) && target_has_registers && target_has_stack && target_has_memory) - restore_selected_frame (old->selected_frame_id, - old->selected_frame_level); -} - -static void -restore_current_thread_cleanup_dtor (void *arg) -{ - struct current_thread_cleanup *old = (struct current_thread_cleanup *) arg; + restore_selected_frame (m_selected_frame_id, m_selected_frame_level); - if (old->thread != NULL) - old->thread->decref (); - - old->inf->decref (); - xfree (old); + if (m_thread != NULL) + m_thread->decref (); + m_inf->decref (); } -struct cleanup * -make_cleanup_restore_current_thread (void) +scoped_restore_current_thread::scoped_restore_current_thread () { - struct current_thread_cleanup *old = XNEW (struct current_thread_cleanup); - - old->thread = NULL; - old->inf = current_inferior (); + m_thread = NULL; + m_inf = current_inferior (); if (inferior_ptid != null_ptid) { + thread_info *tp = find_thread_ptid (inferior_ptid); struct frame_info *frame; - old->was_stopped = is_stopped (inferior_ptid); - if (old->was_stopped + gdb_assert (tp != NULL); + + m_was_stopped = tp->state == THREAD_STOPPED; + if (m_was_stopped && target_has_registers && target_has_stack && target_has_memory) @@ -1656,20 +1636,14 @@ make_cleanup_restore_current_thread (void) else frame = NULL; - old->selected_frame_id = get_frame_id (frame); - old->selected_frame_level = frame_relative_level (frame); - - struct thread_info *tp = find_thread_ptid (inferior_ptid); + m_selected_frame_id = get_frame_id (frame); + m_selected_frame_level = frame_relative_level (frame); - if (tp) - tp->incref (); - old->thread = tp; + m_thread = tp; + m_thread->incref (); } - old->inf->incref (); - - return make_cleanup_dtor (do_restore_current_thread_cleanup, old, - restore_current_thread_cleanup_dtor); + m_inf->incref (); } /* See gdbthread.h. */ @@ -1739,7 +1713,6 @@ tp_array_compar (const thread_info *a, const thread_info *b) static void thread_apply_all_command (char *cmd, int from_tty) { - struct cleanup *old_chain; char *saved_cmd; tp_array_compar_ascending = false; @@ -1755,8 +1728,6 @@ thread_apply_all_command (char *cmd, int from_tty) update_thread_list (); - old_chain = make_cleanup_restore_current_thread (); - /* Save a copy of the command in case it is clobbered by execute_command. */ saved_cmd = xstrdup (cmd); @@ -1790,6 +1761,8 @@ thread_apply_all_command (char *cmd, int from_tty) std::sort (thr_list_cpy.begin (), thr_list_cpy.end (), tp_array_compar); + scoped_restore_current_thread restore_thread; + for (thread_info *thr : thr_list_cpy) if (thread_alive (thr)) { @@ -1803,8 +1776,6 @@ thread_apply_all_command (char *cmd, int from_tty) strcpy (cmd, saved_cmd); } } - - do_cleanups (old_chain); } /* Implementation of the "thread apply" command. */ @@ -1843,7 +1814,7 @@ thread_apply_command (char *tidlist, int from_tty) saved_cmd = xstrdup (cmd); old_chain = make_cleanup (xfree, saved_cmd); - make_cleanup_restore_current_thread (); + scoped_restore_current_thread restore_thread; parser.init (tidlist, current_inferior ()->num); while (!parser.finished () && parser.cur_tok () < cmd) diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index c947c95..a77f01a 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -2930,7 +2930,6 @@ tdump_command (char *args, int from_tty) { int stepping_frame = 0; struct bp_location *loc; - struct cleanup *old_chain; struct command_line *actions; /* This throws an error is not inspecting a trace frame. */ @@ -2941,14 +2940,13 @@ tdump_command (char *args, int from_tty) /* This command only makes sense for the current frame, not the selected frame. */ - old_chain = make_cleanup_restore_current_thread (); + scoped_restore_current_thread restore_thread; + select_frame (get_current_frame ()); actions = all_tracepoint_actions_and_cleanup (loc->owner); trace_dump_actions (actions, 0, stepping_frame, from_tty); - - do_cleanups (old_chain); } /* Encode a piece of a tracepoint's source-level definition in a form diff --git a/gdb/varobj.c b/gdb/varobj.c index 5f21d84..7bd549d 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -2218,14 +2218,13 @@ value_of_root_1 (struct varobj **var_handle) struct value *new_val = NULL; struct varobj *var = *var_handle; int within_scope = 0; - struct cleanup *back_to; /* Only root variables can be updated... */ if (!is_root_p (var)) /* Not a root var. */ return NULL; - back_to = make_cleanup_restore_current_thread (); + scoped_restore_current_thread restore_thread; /* Determine whether the variable is still around. */ if (var->root->valid_block == NULL || var->root->floating) @@ -2264,8 +2263,6 @@ value_of_root_1 (struct varobj **var_handle) END_CATCH } - do_cleanups (back_to); - return new_val; }