From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30532 invoked by alias); 27 Feb 2006 16:43:54 -0000 Received: (qmail 30523 invoked by uid 22791); 27 Feb 2006 16:43:54 -0000 X-Spam-Check-By: sourceware.org Received: from nevyn.them.org (HELO nevyn.them.org) (66.93.172.17) by sourceware.org (qpsmtpd/0.31.1) with ESMTP; Mon, 27 Feb 2006 16:43:51 +0000 Received: from drow by nevyn.them.org with local (Exim 4.54) id 1FDlTR-0005Tt-0L; Mon, 27 Feb 2006 11:43:49 -0500 Date: Mon, 27 Feb 2006 19:28:00 -0000 From: Daniel Jacobowitz To: gdb-patches@sourceware.org Cc: Michael Snyder Subject: Handle fork exit more gracefully in linux-fork.c Message-ID: <20060227164348.GA20931@nevyn.them.org> Mail-Followup-To: gdb-patches@sourceware.org, Michael Snyder Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.8i X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2006-02/txt/msg00494.txt.bz2 A cleanup I made while working on my next patch. I was debugging some checkpoint.exp failures by hand, and the most obvious thing for me to do was to create a checkpoint, let the current one exit, and then continue the previous checkpoint - but as soon as I did this it crashed with corrupted register state. We weren't restoring the saved registers in linux_fork_mourn_inferior. And we were somehow clobbering the previous registers. Moving some bits from the explicit context-switch code into the restore-a-fork routine fixed all that. Look OK? -- Daniel Jacobowitz CodeSourcery 2006-02-27 Daniel Jacobowitz * linux-fork.c: Include "gdb_assert.h". (fork_load_infrun_state): Set inferior_ptid and stop_pc here. Update the register cache and selected frame also. (linux_fork_mourn_inferior): Use fork_load_infrun_state. Return to single fork mode if necessary. (linux_fork_context): Remove bits handled by fork_load_infrun_state. * Makefile.in (linux_fork_h): New. (linux-fork.o, linux-nat.o): Update. Index: src/gdb/linux-fork.c =================================================================== --- src.orig/gdb/linux-fork.c 2006-02-27 10:59:47.000000000 -0500 +++ src/gdb/linux-fork.c 2006-02-27 11:10:45.000000000 -0500 @@ -24,6 +24,7 @@ #include "regcache.h" #include "gdbcmd.h" #include "infcall.h" +#include "gdb_assert.h" #include "gdb_string.h" #include "linux-fork.h" @@ -239,9 +240,19 @@ fork_load_infrun_state (struct fork_info extern void nullify_last_target_wait_ptid (); int i; + inferior_ptid = fp->ptid; + if (fp->savedregs && fp->clobber_regs) regcache_cpy (current_regcache, fp->savedregs); + registers_changed (); + reinit_frame_cache (); + + /* We must select a new frame before making any inferior calls to + avoid warnings. */ + select_frame (get_current_frame ()); + + stop_pc = read_pc (); nullify_last_target_wait_ptid (); /* Now restore the file positions of open file descriptors. */ @@ -354,12 +365,19 @@ linux_fork_mourn_inferior (void) We need to delete that one from the fork_list, and switch to the next available fork. */ delete_fork (inferior_ptid); - if (fork_list) /* Paranoia, shouldn't happen. */ - { - inferior_ptid = fork_list[0].ptid; - printf_filtered (_("[Switching to %s]\n"), - target_pid_to_str (inferior_ptid)); - } + + /* There should still be a fork - if there's only one left, + delete_fork won't remove it, because we haven't updated + inferior_ptid yet. */ + gdb_assert (fork_list); + + fork_load_infrun_state (fork_list); + printf_filtered (_("[Switching to %s]\n"), + target_pid_to_str (inferior_ptid)); + + /* If there's only one fork, switch back to non-fork mode. */ + if (fork_list->next == NULL) + delete_fork (inferior_ptid); } /* Fork list <-> user interface. */ @@ -555,17 +573,10 @@ linux_fork_context (struct fork_info *ne error (_("No such fork/process")); if (!oldfp) - { - oldfp = add_fork (ptid_get_pid (inferior_ptid)); - } + oldfp = add_fork (ptid_get_pid (inferior_ptid)); fork_save_infrun_state (oldfp, 1); - inferior_ptid = newfp->ptid; fork_load_infrun_state (newfp); - registers_changed (); - reinit_frame_cache (); - stop_pc = read_pc (); - select_frame (get_current_frame ()); printf_filtered (_("Switching to %s\n"), target_pid_to_str (inferior_ptid)); Index: src/gdb/Makefile.in =================================================================== --- src.orig/gdb/Makefile.in 2006-02-27 10:59:48.000000000 -0500 +++ src/gdb/Makefile.in 2006-02-27 11:12:35.000000000 -0500 @@ -726,6 +726,7 @@ kod_h = kod.h language_h = language.h libunwind_frame_h = libunwind-frame.h $(libunwind_h) linespec_h = linespec.h +linux_fork_h = linux-fork.h linux_nat_h = linux-nat.h $(target_h) m2_lang_h = m2-lang.h m32r_tdep_h = m32r-tdep.h @@ -2186,12 +2187,13 @@ linespec.o: linespec.c $(defs_h) $(symta $(symfile_h) $(objfiles_h) $(source_h) $(demangle_h) $(value_h) \ $(completer_h) $(cp_abi_h) $(parser_defs_h) $(block_h) \ $(objc_lang_h) $(linespec_h) $(exceptions_h) -linux-fork.o: linux-fork.c linux-fork.h $(defs_h) $(inferior_h) \ - $(regcache_h) $(gdbcmd_h) $(infcall_h) +linux-fork.o: linux-fork.c $(defs_h) $(inferior_h) $(regcache_h) $(gdbcmd_h) \ + $(infcall_h) $(gdb_assert_h) $(gdb_string_h) $(linux_fork_h) linux-nat.o: linux-nat.c $(defs_h) $(inferior_h) $(target_h) $(gdb_string_h) \ $(gdb_wait_h) $(gdb_assert_h) $(linux_nat_h) $(gdbthread_h) \ $(gdbcmd_h) $(regcache_h) $(inf_ptrace.h) $(auxv.h) $(elf_bfd_h) \ - $(gregset_h) $(gdbcore_h) $(gdbthread_h) $(gdb_stat_h) linux-fork.h + $(gregset_h) $(gdbcore_h) $(gdbthread_h) $(gdb_stat_h) \ + $(linux_fork_h) linux-thread-db.o: linux-thread-db.c $(defs_h) $(gdb_assert_h) \ $(gdb_proc_service_h) $(gdb_thread_db_h) $(bfd_h) $(exceptions_h) \ $(gdbthread_h) $(inferior_h) $(symfile_h) $(objfiles_h) $(target_h) \