diff options
author | Pedro Alves <palves@redhat.com> | 2010-04-11 16:33:56 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2010-04-11 16:33:56 +0000 |
commit | 8336d594d5107cb86bf1b569962bf1496e2c7c30 (patch) | |
tree | 6e8f6c708234c278bdf701a1356fca739cd51c86 /gdb/gdbserver/remote-utils.c | |
parent | 5d267c4c705d1d22e21b0dde92750b3afe699681 (diff) | |
download | gdb-8336d594d5107cb86bf1b569962bf1496e2c7c30.zip gdb-8336d594d5107cb86bf1b569962bf1496e2c7c30.tar.gz gdb-8336d594d5107cb86bf1b569962bf1496e2c7c30.tar.bz2 |
GDBserver disconnected tracing support.
* linux-low.c (linux_remove_process): Delete.
(add_lwp): Don't set last_resume_kind here.
(linux_kill): Use `mourn'.
(linux_detach): Use `thread_db_detach', and `mourn'.
(linux_mourn): New.
(linux_attach_lwp_1): Adjust comment.
(linux_attach): last_resume_kind moved the thread_info; adjust.
(status_pending_p_callback): Adjust.
(linux_wait_for_event_1): Adjust.
(count_events_callback, select_singlestep_lwp_callback)
(select_event_lwp_callback, cancel_breakpoints_callback)
(db_wants_lwp_stopped, linux_wait_1, need_step_over_p)
(proceed_one_lwp): Adjust.
(linux_async): Add debug output.
(linux_thread_stopped): New.
(linux_pause_all): New.
(linux_target_ops): Install linux_mourn, linux_thread_stopped and
linux_pause_all.
* linux-low.h (struct lwp_info): Delete last_resume_kind field.
(thread_db_free): Delete declaration.
(thread_db_detach, thread_db_mourn): Declare.
* thread-db.c (thread_db_init): Use thread_db_mourn.
(thread_db_free): Delete, split in two.
(disable_thread_event_reporting): New.
(thread_db_detach): New.
(thread_db_mourn): New.
* server.h (struct thread_info) <last_resume_kind>: New field.
<attached>: Add comment.
<gdb_detached>: New field.
(handler_func): Change return type to int.
(handle_serial_event, handle_target_event): Ditto.
(gdb_connected): Declare.
(tracing): Delete.
(disconnected_tracing): Declare.
(stop_tracing): Declare.
* server.c (handle_query) <qSupported>: Report support for
disconnected tracing.
(queue_stop_reply_callback): Account for running threads.
(gdb_wants_thread_stopped): New.
(gdb_wants_all_threads_stopped): New.
(gdb_reattached_process): New.
(handle_status): Clear the `gdb_detached' flag of all processes.
In all-stop, stop all threads.
(main): Be sure to leave tfind mode. Handle disconnected tracing.
(process_serial_event): If the remote connection breaks, or if an
exit was forced with "monitor exit", force an event loop exit.
Handle disconnected tracing on detach.
(handle_serial_event): Adjust.
(handle_target_event): If GDB isn't connected, forward events back
to the inferior, unless the last process exited, in which case,
exit gdbserver. Adjust interface.
* remote-utils.c (remote_open): Don't block in accept. Instead
register an event loop source on the listen socket file
descriptor. Refactor bits into ...
(listen_desc): ... this new global.
(gdb_connected): ... this new function.
(enable_async_notification): ... this new function.
(handle_accept_event): ... this new function.
(remote_close): Clear remote_desc.
* inferiors.c (add_thread): Set the new thread's last_resume_kind.
* target.h (struct target_ops) <mourn, thread_stopped, pause_all>:
New fields.
(mourn_inferior): Define.
(target_process_qsupported): Avoid the dangling else problem.
(thread_stopped): Define.
(pause_all): Define.
(target_waitstatus_to_string): Declare.
* target.c (target_waitstatus_to_string): New.
* tracepoint.c (tracing): Make extern.
(disconnected_tracing): New.
(stop_tracing): Make extern. Handle tracing stops due to GDB
disconnecting.
(cmd_qtdisconnected): New.
(cmd_qtstatus): Report disconnected tracing status in trace reply.
(handle_tracepoint_general_set): Handle QTDisconnected.
* event-loop.c (event_handler_func): Change return type to int.
(process_event): Bail out if the event handler wants the event
loop to stop.
(handle_file_event): Ditto.
(start_event_loop): Bail out if the event handler wants the event
loop to stop.
* nto-low.c (nto_target_ops): Adjust.
* spu-low.c (spu_wait): Don't remove the process here.
(spu_target_ops): Adjust.
* win32-low.c (win32_wait): Don't remove the process here.
(win32_target_ops): Adjust.
Diffstat (limited to 'gdb/gdbserver/remote-utils.c')
-rw-r--r-- | gdb/gdbserver/remote-utils.c | 143 |
1 files changed, 92 insertions, 51 deletions
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c index 7cd1e2d..6a93c3a 100644 --- a/gdb/gdbserver/remote-utils.c +++ b/gdb/gdbserver/remote-utils.c @@ -92,6 +92,7 @@ int remote_debug = 0; struct ui_file *gdb_stdlog; static int remote_desc = INVALID_DESCRIPTOR; +static int listen_desc = INVALID_DESCRIPTOR; /* FIXME headerize? */ extern int using_threads; @@ -107,15 +108,88 @@ int transport_is_reliable = 0; # define write(fd, buf, len) send (fd, (char *) buf, len, 0) #endif +int +gdb_connected (void) +{ + return remote_desc != INVALID_DESCRIPTOR; +} + +static void +enable_async_notification (int fd) +{ +#if defined(F_SETFL) && defined (FASYNC) + int save_fcntl_flags; + + save_fcntl_flags = fcntl (fd, F_GETFL, 0); + fcntl (fd, F_SETFL, save_fcntl_flags | FASYNC); +#if defined (F_SETOWN) + fcntl (fd, F_SETOWN, getpid ()); +#endif +#endif +} + +static int +handle_accept_event (int err, gdb_client_data client_data) +{ + struct sockaddr_in sockaddr; + socklen_t tmp; + + if (debug_threads) + fprintf (stderr, "handling possible accept event\n"); + + tmp = sizeof (sockaddr); + remote_desc = accept (listen_desc, (struct sockaddr *) &sockaddr, &tmp); + if (remote_desc == -1) + perror_with_name ("Accept failed"); + + /* Enable TCP keep alive process. */ + tmp = 1; + setsockopt (remote_desc, SOL_SOCKET, SO_KEEPALIVE, + (char *) &tmp, sizeof (tmp)); + + /* Tell TCP not to delay small packets. This greatly speeds up + interactive response. */ + tmp = 1; + setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, + (char *) &tmp, sizeof (tmp)); + +#ifndef USE_WIN32API + close (listen_desc); /* No longer need this */ + + signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply + exits when the remote side dies. */ +#else + closesocket (listen_desc); /* No longer need this */ +#endif + + delete_file_handler (listen_desc); + + /* Convert IP address to string. */ + fprintf (stderr, "Remote debugging from host %s\n", + inet_ntoa (sockaddr.sin_addr)); + + enable_async_notification (remote_desc); + + /* Register the event loop handler. */ + add_file_handler (remote_desc, handle_serial_event, NULL); + + /* We have a new GDB connection now. If we were disconnected + tracing, there's a window where the target could report a stop + event to the event loop, and since we have a connection now, we'd + try to send vStopped notifications to GDB. But, don't do that + until GDB as selected all-stop/non-stop, and has queried the + threads' status ('?'). */ + target_async (0); + + return 0; +} + /* Open a connection to a remote debugger. NAME is the filename used for communication. */ void remote_open (char *name) { -#if defined(F_SETFL) && defined (FASYNC) - int save_fcntl_flags; -#endif char *port_str; port_str = strchr (name, ':'); @@ -183,9 +257,14 @@ remote_open (char *name) #endif fprintf (stderr, "Remote debugging using %s\n", name); -#endif /* USE_WIN32API */ transport_is_reliable = 0; + + enable_async_notification (remote_desc); + + /* Register the event loop handler. */ + add_file_handler (remote_desc, handle_serial_event, NULL); +#endif /* USE_WIN32API */ } else { @@ -195,7 +274,6 @@ remote_open (char *name) int port; struct sockaddr_in sockaddr; socklen_t tmp; - int tmp_desc; char *port_end; port = strtoul (port_str + 1, &port_end, 10); @@ -212,21 +290,21 @@ remote_open (char *name) } #endif - tmp_desc = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (tmp_desc < 0) + listen_desc = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (listen_desc < 0) perror_with_name ("Can't open socket"); /* Allow rapid reuse of this port. */ tmp = 1; - setsockopt (tmp_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, + setsockopt (listen_desc, SOL_SOCKET, SO_REUSEADDR, (char *) &tmp, sizeof (tmp)); sockaddr.sin_family = PF_INET; sockaddr.sin_port = htons (port); sockaddr.sin_addr.s_addr = INADDR_ANY; - if (bind (tmp_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) - || listen (tmp_desc, 1)) + if (bind (listen_desc, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) + || listen (listen_desc, 1)) perror_with_name ("Can't bind address"); /* If port is zero, a random port will be selected, and the @@ -234,7 +312,7 @@ remote_open (char *name) if (port == 0) { socklen_t len = sizeof (sockaddr); - if (getsockname (tmp_desc, (struct sockaddr *) &sockaddr, &len) < 0 + if (getsockname (listen_desc, (struct sockaddr *) &sockaddr, &len) < 0 || len < sizeof (sockaddr)) perror_with_name ("Can't determine port"); port = ntohs (sockaddr.sin_port); @@ -243,49 +321,11 @@ remote_open (char *name) fprintf (stderr, "Listening on port %d\n", port); fflush (stderr); - tmp = sizeof (sockaddr); - remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp); - if (remote_desc == -1) - perror_with_name ("Accept failed"); - - /* Enable TCP keep alive process. */ - tmp = 1; - setsockopt (remote_desc, SOL_SOCKET, SO_KEEPALIVE, - (char *) &tmp, sizeof (tmp)); - - /* Tell TCP not to delay small packets. This greatly speeds up - interactive response. */ - tmp = 1; - setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY, - (char *) &tmp, sizeof (tmp)); - - -#ifndef USE_WIN32API - close (tmp_desc); /* No longer need this */ - - signal (SIGPIPE, SIG_IGN); /* If we don't do this, then gdbserver simply - exits when the remote side dies. */ -#else - closesocket (tmp_desc); /* No longer need this */ -#endif - - /* Convert IP address to string. */ - fprintf (stderr, "Remote debugging from host %s\n", - inet_ntoa (sockaddr.sin_addr)); + /* Register the event loop handler. */ + add_file_handler (listen_desc, handle_accept_event, NULL); transport_is_reliable = 1; } - -#if defined(F_SETFL) && defined (FASYNC) - save_fcntl_flags = fcntl (remote_desc, F_GETFL, 0); - fcntl (remote_desc, F_SETFL, save_fcntl_flags | FASYNC); -#if defined (F_SETOWN) - fcntl (remote_desc, F_SETOWN, getpid ()); -#endif -#endif - - /* Register the event loop handler. */ - add_file_handler (remote_desc, handle_serial_event, NULL); } void @@ -298,6 +338,7 @@ remote_close (void) #else close (remote_desc); #endif + remote_desc = INVALID_DESCRIPTOR; } /* Convert hex digit A to a number. */ |