From patchwork Mon Aug 18 08:46:58 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gary Benson X-Patchwork-Id: 2415 Received: (qmail 9102 invoked by alias); 18 Aug 2014 09:25:10 -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 9088 invoked by uid 89); 18 Aug 2014 09:25:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 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 (AES256-GCM-SHA384 encrypted) ESMTPS; Mon, 18 Aug 2014 09:25:06 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s7I8l5fA002414 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Mon, 18 Aug 2014 04:47:05 -0400 Received: from blade.nx (ovpn-116-90.ams2.redhat.com [10.36.116.90]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s7I8l3aD029751 for ; Mon, 18 Aug 2014 04:47:04 -0400 Received: from blade.nx (localhost [127.0.0.1]) by blade.nx (Postfix) with ESMTP id B5A2C2640EA for ; Mon, 18 Aug 2014 09:47:00 +0100 (BST) From: Gary Benson To: gdb-patches@sourceware.org Subject: [PATCH 5/5] Use exceptions and cleanups in gdbserver Date: Mon, 18 Aug 2014 09:46:58 +0100 Message-Id: <1408351618-21013-6-git-send-email-gbenson@redhat.com> In-Reply-To: <1408351618-21013-1-git-send-email-gbenson@redhat.com> References: <1408351618-21013-1-git-send-email-gbenson@redhat.com> X-IsSubscribed: yes This commit replaces the hacky "exception" system in gdbserver with the exceptions and cleanups subsystem from GDB. Only the catch/cleanup code in what was "main" has been updated to use the new system. Other parts of gdbserver could likely be converted to TRY_CATCH and cleanups too, but that can be done on an as-needed basis if this patch is accepted. A side-effect of this patch is that some error messages will change slightly, and in cases with multiple errors the error messages will be printed in a different order. gdb/gdbserver/ 2014-08-18 Gary Benson * server.h (setjmp.h): Do not include. (toplevel): Do not declare. * server.c (common-exceptions.h): Include. (cleanups.h): Likewise. (toplevel): Do not define. (exit_code): New static global. (detach_or_kill_for_exit_cleanup): New function. (main): New function. Original main renamed to... (captured_main): New function. * utils.c (common-exceptions.h): Include. (verror) [!IN_PROCESS_AGENT]: Use throw_verror. --- gdb/gdbserver/ChangeLog | 14 ++++ gdb/gdbserver/server.c | 196 ++++++++++++++++++++++++++--------------------- gdb/gdbserver/server.h | 4 - gdb/gdbserver/utils.c | 11 +-- 4 files changed, 127 insertions(+), 98 deletions(-) diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 500260c..aec70f0 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -35,6 +35,8 @@ #include "tracepoint.h" #include "dll.h" #include "hostio.h" +#include "common-exceptions.h" +#include "cleanups.h" /* The thread set with an `Hc' packet. `Hc' is deprecated in favor of `vCont'. Note the multi-process extensions made `vCont' a @@ -73,8 +75,6 @@ int pass_signals[GDB_SIGNAL_LAST]; int program_signals[GDB_SIGNAL_LAST]; int program_signals_p; -jmp_buf toplevel; - /* The PID of the originally created or attached inferior. Used to send signals to the process when GDB sends us an asynchronous interrupt (user hitting Control-C in the client), and to wait for the child to exit @@ -3010,8 +3010,34 @@ detach_or_kill_for_exit (void) for_each_inferior (&all_processes, detach_or_kill_inferior_callback); } -int -main (int argc, char *argv[]) +/* Value that will be passed to exit(3) when gdbserver exits. */ +static int exit_code; + +/* Cleanup version of detach_or_kill_for_exit. */ + +static void +detach_or_kill_for_exit_cleanup (void *ignore) +{ + volatile struct gdb_exception exception; + + TRY_CATCH (exception, RETURN_MASK_ALL) + { + detach_or_kill_for_exit (); + } + + if (exception.reason < 0) + { + fflush (stdout); + fprintf (stderr, "Detach or kill failed: %s\n", exception.message); + exit_code = 1; + } +} + +/* Main function. This is called by the real "main" function, + wrapped in a TRY_CATCH that handles any uncaught exceptions. */ + +static void ATTRIBUTE_NORETURN +captured_main (int argc, char *argv[]) { int bad_attach; int pid; @@ -3135,12 +3161,6 @@ main (int argc, char *argv[]) continue; } - if (setjmp (toplevel)) - { - fprintf (stderr, "Exiting\n"); - exit (1); - } - port = *next_arg; next_arg++; if (port == NULL || (!attach && !multi_mode && *next_arg == NULL)) @@ -3223,6 +3243,7 @@ main (int argc, char *argv[]) last_status.value.integer = 0; last_ptid = minus_one_ptid; } + make_cleanup (detach_or_kill_for_exit_cleanup, NULL); initialize_notif (); @@ -3231,19 +3252,6 @@ main (int argc, char *argv[]) shared library event" notice on gdb side. */ dlls_changed = 0; - if (setjmp (toplevel)) - { - /* If something fails and longjmps while detaching or killing - inferiors, we'd end up here again, stuck in an infinite loop - trap. Be sure that if that happens, we exit immediately - instead. */ - if (setjmp (toplevel) == 0) - detach_or_kill_for_exit (); - else - fprintf (stderr, "Detach or kill failed. Exiting\n"); - exit (1); - } - if (last_status.kind == TARGET_WAITKIND_EXITED || last_status.kind == TARGET_WAITKIND_SIGNALLED) was_running = 0; @@ -3251,13 +3259,12 @@ main (int argc, char *argv[]) was_running = 1; if (!was_running && !multi_mode) - { - fprintf (stderr, "No program to debug. GDBserver exiting.\n"); - exit (1); - } + error ("No program to debug"); while (1) { + volatile struct gdb_exception exception; + noack_mode = 0; multi_process = 0; /* Be sure we're out of tfind mode. */ @@ -3265,82 +3272,97 @@ main (int argc, char *argv[]) remote_open (port); - if (setjmp (toplevel) != 0) + TRY_CATCH (exception, RETURN_MASK_ERROR) { - /* An error occurred. */ - if (response_needed) - { - write_enn (own_buf); - putpkt (own_buf); - } - } - - /* Wait for events. This will return when all event sources are - removed from the event loop. */ - start_event_loop (); + /* Wait for events. This will return when all event sources + are removed from the event loop. */ + start_event_loop (); - /* If an exit was requested (using the "monitor exit" command), - terminate now. The only other way to get here is for - getpkt to fail; close the connection and reopen it at the - top of the loop. */ + /* If an exit was requested (using the "monitor exit" + command), terminate now. The only other way to get + here is for getpkt to fail; close the connection + and reopen it at the top of the loop. */ - if (exit_requested || run_once) - { - /* If something fails and longjmps while detaching or - killing inferiors, we'd end up here again, stuck in an - infinite loop trap. Be sure that if that happens, we - exit immediately instead. */ - if (setjmp (toplevel) == 0) - { - detach_or_kill_for_exit (); - exit (0); - } - else - { - fprintf (stderr, "Detach or kill failed. Exiting\n"); - exit (1); - } - } + if (exit_requested || run_once) + throw_quit ("Quit"); - fprintf (stderr, - "Remote side has terminated connection. " - "GDBserver will reopen the connection.\n"); + fprintf (stderr, + "Remote side has terminated connection. " + "GDBserver will reopen the connection.\n"); - /* Get rid of any pending statuses. An eventual reconnection - (by the same GDB instance or another) will refresh all its - state from scratch. */ - discard_queued_stop_replies (-1); - for_each_inferior (&all_threads, clear_pending_status_callback); + /* Get rid of any pending statuses. An eventual reconnection + (by the same GDB instance or another) will refresh all its + state from scratch. */ + discard_queued_stop_replies (-1); + for_each_inferior (&all_threads, + clear_pending_status_callback); - if (tracing) - { - if (disconnected_tracing) + if (tracing) { - /* Try to enable non-stop/async mode, so we we can both - wait for an async socket accept, and handle async - target events simultaneously. There's also no point - either in having the target always stop all threads, - when we're going to pass signals down without - informing GDB. */ - if (!non_stop) + if (disconnected_tracing) { - if (start_non_stop (1)) - non_stop = 1; + /* Try to enable non-stop/async mode, so we we can + both wait for an async socket accept, and handle + async target events simultaneously. There's also + no point either in having the target always stop + all threads, when we're going to pass signals + down without informing GDB. */ + if (!non_stop) + { + if (start_non_stop (1)) + non_stop = 1; - /* Detaching implicitly resumes all threads; simply - disconnecting does not. */ + /* Detaching implicitly resumes all threads; + simply disconnecting does not. */ + } + } + else + { + fprintf (stderr, + "Disconnected tracing disabled; " + "stopping trace run.\n"); + stop_tracing (); } } - else + } + + if (exception.reason == RETURN_ERROR) + { + if (response_needed) { - fprintf (stderr, - "Disconnected tracing disabled; stopping trace run.\n"); - stop_tracing (); + write_enn (own_buf); + putpkt (own_buf); } } } } +/* Main function. */ + +int +main (int argc, char *argv[]) +{ + volatile struct gdb_exception exception; + + TRY_CATCH (exception, RETURN_MASK_ALL) + { + captured_main (argc, argv); + } + + /* captured_main should never return. */ + gdb_assert (exception.reason < 0); + + if (exception.reason == RETURN_ERROR) + { + fflush (stdout); + fprintf (stderr, "%s\n", exception.message); + fprintf (stderr, "Exiting\n"); + exit_code = 1; + } + + exit (exit_code); +} + /* Skip PACKET until the next semi-colon (or end of string). */ static void diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h index 97498a6..cac73e9 100644 --- a/gdb/gdbserver/server.h +++ b/gdb/gdbserver/server.h @@ -29,8 +29,6 @@ gdb_static_assert (sizeof (CORE_ADDR) >= sizeof (void *)); #include "version.h" -#include - #ifdef HAVE_ALLOCA_H #include #endif @@ -88,8 +86,6 @@ extern int pass_signals[]; extern int program_signals[]; extern int program_signals_p; -extern jmp_buf toplevel; - extern int disable_packet_vCont; extern int disable_packet_Tthread; extern int disable_packet_qC; diff --git a/gdb/gdbserver/utils.c b/gdb/gdbserver/utils.c index 6283877..e2eb4f4 100644 --- a/gdb/gdbserver/utils.c +++ b/gdb/gdbserver/utils.c @@ -17,6 +17,7 @@ along with this program. If not, see . */ #include "server.h" +#include "common-exceptions.h" #ifdef IN_PROCESS_AGENT # define PREFIX "ipa: " @@ -76,17 +77,13 @@ perror_with_name (const char *string) void verror (const char *string, va_list args) { -#ifndef IN_PROCESS_AGENT - extern jmp_buf toplevel; -#endif - +#ifdef IN_PROCESS_AGENT fflush (stdout); vfprintf (stderr, string, args); fprintf (stderr, "\n"); -#ifndef IN_PROCESS_AGENT - longjmp (toplevel, 1); -#else exit (1); +#else + throw_verror (GENERIC_ERROR, string, args); #endif }