mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-29 02:20:51 +00:00
inf-ptrace: Add an event_pipe to be used for async mode in subclasses.
Subclasses of inf_ptrace_target have to opt-in to using the event_pipe by implementing the can_async_p and async methods. For subclasses which do this, inf_ptrace_target provides is_async_p, async_wait_fd and closes the pipe in the close target method. inf_ptrace_target also provides wrapper routines around the event pipe (async_file_open, async_file_close, async_file_flush, and async_file_mark) for use in target methods such as async. inf_ptrace_target also exports a static async_file_mark_if_open function which can be used in SIGCHLD signal handlers.
This commit is contained in:
@@ -21,7 +21,6 @@
|
||||
#include "gdbsupport/block-signals.h"
|
||||
#include "gdbsupport/byte-vector.h"
|
||||
#include "gdbsupport/event-loop.h"
|
||||
#include "gdbsupport/event-pipe.h"
|
||||
#include "gdbcore.h"
|
||||
#include "inferior.h"
|
||||
#include "regcache.h"
|
||||
@@ -932,8 +931,6 @@ fbsd_nat_target::update_thread_list ()
|
||||
|
||||
/* Async mode support. */
|
||||
|
||||
static event_pipe fbsd_nat_event_pipe;
|
||||
|
||||
/* Implement the "can_async_p" target method. */
|
||||
|
||||
bool
|
||||
@@ -946,22 +943,6 @@ fbsd_nat_target::can_async_p ()
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Implement the "is_async_p" target method. */
|
||||
|
||||
bool
|
||||
fbsd_nat_target::is_async_p ()
|
||||
{
|
||||
return fbsd_nat_event_pipe.is_open ();
|
||||
}
|
||||
|
||||
/* Implement the "async_wait_fd" target method. */
|
||||
|
||||
int
|
||||
fbsd_nat_target::async_wait_fd ()
|
||||
{
|
||||
return fbsd_nat_event_pipe.event_fd ();
|
||||
}
|
||||
|
||||
/* SIGCHLD handler notifies the event-loop in async mode. */
|
||||
|
||||
static void
|
||||
@@ -969,8 +950,7 @@ sigchld_handler (int signo)
|
||||
{
|
||||
int old_errno = errno;
|
||||
|
||||
if (fbsd_nat_event_pipe.is_open ())
|
||||
fbsd_nat_event_pipe.mark ();
|
||||
fbsd_nat_target::async_file_mark_if_open ();
|
||||
|
||||
errno = old_errno;
|
||||
}
|
||||
@@ -997,34 +977,22 @@ fbsd_nat_target::async (int enable)
|
||||
|
||||
if (enable)
|
||||
{
|
||||
if (!fbsd_nat_event_pipe.open ())
|
||||
if (!async_file_open ())
|
||||
internal_error (__FILE__, __LINE__, "failed to create event pipe.");
|
||||
|
||||
add_file_handler (fbsd_nat_event_pipe.event_fd (),
|
||||
handle_target_event, NULL, "fbsd-nat");
|
||||
add_file_handler (async_wait_fd (), handle_target_event, NULL, "fbsd-nat");
|
||||
|
||||
/* Trigger a poll in case there are pending events to
|
||||
handle. */
|
||||
fbsd_nat_event_pipe.mark ();
|
||||
async_file_mark ();
|
||||
}
|
||||
else
|
||||
{
|
||||
delete_file_handler (fbsd_nat_event_pipe.event_fd ());
|
||||
fbsd_nat_event_pipe.close ();
|
||||
delete_file_handler (async_wait_fd ());
|
||||
async_file_close ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement the "close" target method. */
|
||||
|
||||
void
|
||||
fbsd_nat_target::close ()
|
||||
{
|
||||
if (is_async_p ())
|
||||
async (0);
|
||||
|
||||
inf_ptrace_target::close ();
|
||||
}
|
||||
|
||||
#ifdef TDP_RFPPWAIT
|
||||
/*
|
||||
To catch fork events, PT_FOLLOW_FORK is set on every traced process
|
||||
@@ -1100,7 +1068,7 @@ fbsd_add_vfork_done (ptid_t pid)
|
||||
/* If we're in async mode, need to tell the event loop there's
|
||||
something here to process. */
|
||||
if (target_is_async_p ())
|
||||
fbsd_nat_event_pipe.mark ();
|
||||
async_file_mark ();
|
||||
}
|
||||
|
||||
/* Check for a pending vfork done event for a specific PID. */
|
||||
@@ -1499,7 +1467,7 @@ fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
|
||||
/* Ensure any subsequent events trigger a new event in the loop. */
|
||||
if (is_async_p ())
|
||||
fbsd_nat_event_pipe.flush ();
|
||||
async_file_flush ();
|
||||
|
||||
wptid = wait_1 (ptid, ourstatus, target_options);
|
||||
|
||||
@@ -1510,7 +1478,7 @@ fbsd_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
|
||||
&& ((ourstatus->kind () != TARGET_WAITKIND_IGNORE
|
||||
&& ourstatus->kind() != TARGET_WAITKIND_NO_RESUMED)
|
||||
|| ptid != minus_one_ptid))
|
||||
fbsd_nat_event_pipe.mark ();
|
||||
async_file_mark ();
|
||||
|
||||
fbsd_nat_debug_printf ("returning [%s], [%s]",
|
||||
target_pid_to_str (wptid).c_str (),
|
||||
|
||||
@@ -67,13 +67,9 @@ public:
|
||||
void update_thread_list () override;
|
||||
|
||||
bool can_async_p () override;
|
||||
bool is_async_p () override;
|
||||
|
||||
int async_wait_fd () override;
|
||||
void async (int) override;
|
||||
|
||||
void close () override;
|
||||
|
||||
thread_control_capabilities get_thread_control_capabilities () override
|
||||
{ return tc_schedlock; }
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ gdb_ptrace (PTRACE_TYPE_ARG1 request, ptid_t ptid, PTRACE_TYPE_ARG3 addr,
|
||||
#endif
|
||||
}
|
||||
|
||||
/* The event pipe registered as a waitable file in the event loop. */
|
||||
event_pipe inf_ptrace_target::m_event_pipe;
|
||||
|
||||
inf_ptrace_target::~inf_ptrace_target ()
|
||||
{}
|
||||
|
||||
@@ -527,3 +530,15 @@ inf_ptrace_target::pid_to_str (ptid_t ptid)
|
||||
{
|
||||
return normal_pid_to_str (ptid);
|
||||
}
|
||||
|
||||
/* Implement the "close" target method. */
|
||||
|
||||
void
|
||||
inf_ptrace_target::close ()
|
||||
{
|
||||
/* Unregister from the event loop. */
|
||||
if (is_async_p ())
|
||||
async (0);
|
||||
|
||||
inf_child_target::close ();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#ifndef INF_PTRACE_H
|
||||
#define INF_PTRACE_H
|
||||
|
||||
#include "gdbsupport/event-pipe.h"
|
||||
#include "inf-child.h"
|
||||
|
||||
/* An abstract prototype ptrace target. The client can override it
|
||||
@@ -33,6 +34,8 @@ struct inf_ptrace_target : public inf_child_target
|
||||
|
||||
void detach (inferior *inf, int) override;
|
||||
|
||||
void close () override;
|
||||
|
||||
void resume (ptid_t, int, enum gdb_signal) override;
|
||||
|
||||
ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
|
||||
@@ -57,7 +60,31 @@ struct inf_ptrace_target : public inf_child_target
|
||||
ULONGEST offset, ULONGEST len,
|
||||
ULONGEST *xfered_len) override;
|
||||
|
||||
bool is_async_p () override
|
||||
{ return m_event_pipe.is_open (); }
|
||||
|
||||
int async_wait_fd () override
|
||||
{ return m_event_pipe.event_fd (); }
|
||||
|
||||
/* Helper routine used from SIGCHLD handlers to signal the async
|
||||
event pipe. */
|
||||
static void async_file_mark_if_open ()
|
||||
{
|
||||
if (m_event_pipe.is_open ())
|
||||
m_event_pipe.mark ();
|
||||
}
|
||||
|
||||
protected:
|
||||
/* Helper routines for interacting with the async event pipe. */
|
||||
bool async_file_open ()
|
||||
{ return m_event_pipe.open (); }
|
||||
void async_file_close ()
|
||||
{ m_event_pipe.close (); }
|
||||
void async_file_flush ()
|
||||
{ m_event_pipe.flush (); }
|
||||
void async_file_mark ()
|
||||
{ m_event_pipe.mark (); }
|
||||
|
||||
/* Cleanup the inferior after a successful ptrace detach. */
|
||||
void detach_success (inferior *inf);
|
||||
|
||||
@@ -71,6 +98,9 @@ protected:
|
||||
Such targets will supply an appropriate definition for this
|
||||
function. */
|
||||
virtual void post_startup_inferior (ptid_t ptid) = 0;
|
||||
|
||||
private:
|
||||
static event_pipe m_event_pipe;
|
||||
};
|
||||
|
||||
#ifndef __NetBSD__
|
||||
|
||||
123
gdb/linux-nat.c
123
gdb/linux-nat.c
@@ -48,7 +48,6 @@
|
||||
#include <fcntl.h> /* for O_RDONLY */
|
||||
#include "inf-loop.h"
|
||||
#include "gdbsupport/event-loop.h"
|
||||
#include "gdbsupport/event-pipe.h"
|
||||
#include "event-top.h"
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
@@ -66,6 +65,7 @@
|
||||
#include "gdbsupport/filestuff.h"
|
||||
#include "objfiles.h"
|
||||
#include "nat/linux-namespaces.h"
|
||||
#include "gdbsupport/block-signals.h"
|
||||
#include "gdbsupport/fileio.h"
|
||||
#include "gdbsupport/scope-exit.h"
|
||||
#include "gdbsupport/gdb-sigmask.h"
|
||||
@@ -227,32 +227,6 @@ static struct simple_pid_list *stopped_pids;
|
||||
/* Whether target_thread_events is in effect. */
|
||||
static int report_thread_events;
|
||||
|
||||
/* Async mode support. */
|
||||
|
||||
/* The event pipe registered as a waitable file in the event loop. */
|
||||
static event_pipe linux_nat_event_pipe;
|
||||
|
||||
/* True if we're currently in async mode. */
|
||||
#define linux_is_async_p() (linux_nat_event_pipe.is_open ())
|
||||
|
||||
/* Flush the event pipe. */
|
||||
|
||||
static void
|
||||
async_file_flush (void)
|
||||
{
|
||||
linux_nat_event_pipe.flush ();
|
||||
}
|
||||
|
||||
/* Put something (anything, doesn't matter what, or how much) in event
|
||||
pipe, so that the select/poll in the event-loop realizes we have
|
||||
something to process. */
|
||||
|
||||
static void
|
||||
async_file_mark (void)
|
||||
{
|
||||
linux_nat_event_pipe.mark ();
|
||||
}
|
||||
|
||||
static int kill_lwp (int lwpid, int signo);
|
||||
|
||||
static int stop_callback (struct lwp_info *lp);
|
||||
@@ -4054,14 +4028,6 @@ linux_nat_target::static_tracepoint_markers_by_strid (const char *strid)
|
||||
return markers;
|
||||
}
|
||||
|
||||
/* target_is_async_p implementation. */
|
||||
|
||||
bool
|
||||
linux_nat_target::is_async_p ()
|
||||
{
|
||||
return linux_is_async_p ();
|
||||
}
|
||||
|
||||
/* target_can_async_p implementation. */
|
||||
|
||||
bool
|
||||
@@ -4113,10 +4079,11 @@ sigchld_handler (int signo)
|
||||
if (debug_linux_nat)
|
||||
gdb_stdlog->write_async_safe ("sigchld\n", sizeof ("sigchld\n") - 1);
|
||||
|
||||
if (signo == SIGCHLD
|
||||
&& linux_nat_event_pipe.is_open ())
|
||||
async_file_mark (); /* Let the event loop know that there are
|
||||
events to handle. */
|
||||
if (signo == SIGCHLD)
|
||||
{
|
||||
/* Let the event loop know that there are events to handle. */
|
||||
linux_nat_target::async_file_mark_if_open ();
|
||||
}
|
||||
|
||||
errno = old_errno;
|
||||
}
|
||||
@@ -4129,67 +4096,35 @@ handle_target_event (int error, gdb_client_data client_data)
|
||||
inferior_event_handler (INF_REG_EVENT);
|
||||
}
|
||||
|
||||
/* Create/destroy the target events pipe. Returns previous state. */
|
||||
|
||||
static int
|
||||
linux_async_pipe (int enable)
|
||||
{
|
||||
int previous = linux_is_async_p ();
|
||||
|
||||
if (previous != enable)
|
||||
{
|
||||
sigset_t prev_mask;
|
||||
|
||||
/* Block child signals while we create/destroy the pipe, as
|
||||
their handler writes to it. */
|
||||
block_child_signals (&prev_mask);
|
||||
|
||||
if (enable)
|
||||
{
|
||||
if (!linux_nat_event_pipe.open ())
|
||||
internal_error (__FILE__, __LINE__,
|
||||
"creating event pipe failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
linux_nat_event_pipe.close ();
|
||||
}
|
||||
|
||||
restore_child_signals_mask (&prev_mask);
|
||||
}
|
||||
|
||||
return previous;
|
||||
}
|
||||
|
||||
int
|
||||
linux_nat_target::async_wait_fd ()
|
||||
{
|
||||
return linux_nat_event_pipe.event_fd ();
|
||||
}
|
||||
|
||||
/* target_async implementation. */
|
||||
|
||||
void
|
||||
linux_nat_target::async (int enable)
|
||||
{
|
||||
if ((enable != 0) == is_async_p ())
|
||||
return;
|
||||
|
||||
/* Block child signals while we create/destroy the pipe, as their
|
||||
handler writes to it. */
|
||||
gdb::block_signals blocker;
|
||||
|
||||
if (enable)
|
||||
{
|
||||
if (!linux_async_pipe (1))
|
||||
{
|
||||
add_file_handler (linux_nat_event_pipe.event_fd (),
|
||||
handle_target_event, NULL,
|
||||
"linux-nat");
|
||||
/* There may be pending events to handle. Tell the event loop
|
||||
to poll them. */
|
||||
async_file_mark ();
|
||||
}
|
||||
if (!async_file_open ())
|
||||
internal_error (__FILE__, __LINE__, "creating event pipe failed.");
|
||||
|
||||
add_file_handler (async_wait_fd (), handle_target_event, NULL,
|
||||
"linux-nat");
|
||||
|
||||
/* There may be pending events to handle. Tell the event loop
|
||||
to poll them. */
|
||||
async_file_mark ();
|
||||
}
|
||||
else
|
||||
{
|
||||
delete_file_handler (linux_nat_event_pipe.event_fd ());
|
||||
linux_async_pipe (0);
|
||||
delete_file_handler (async_wait_fd ());
|
||||
async_file_close ();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Stop an LWP, and push a GDB_SIGNAL_0 stop status if no other
|
||||
@@ -4238,16 +4173,6 @@ linux_nat_target::stop (ptid_t ptid)
|
||||
iterate_over_lwps (ptid, linux_nat_stop_lwp);
|
||||
}
|
||||
|
||||
void
|
||||
linux_nat_target::close ()
|
||||
{
|
||||
/* Unregister from the event loop. */
|
||||
if (is_async_p ())
|
||||
async (0);
|
||||
|
||||
inf_ptrace_target::close ();
|
||||
}
|
||||
|
||||
/* When requests are passed down from the linux-nat layer to the
|
||||
single threaded inf-ptrace layer, ptids of (lwpid,0,0) form are
|
||||
used. The address space pointer is stored in the inferior object,
|
||||
|
||||
@@ -83,16 +83,12 @@ public:
|
||||
void thread_events (int) override;
|
||||
|
||||
bool can_async_p () override;
|
||||
bool is_async_p () override;
|
||||
|
||||
bool supports_non_stop () override;
|
||||
bool always_non_stop_p () override;
|
||||
|
||||
int async_wait_fd () override;
|
||||
void async (int) override;
|
||||
|
||||
void close () override;
|
||||
|
||||
void stop (ptid_t) override;
|
||||
|
||||
bool supports_multi_process () override;
|
||||
|
||||
Reference in New Issue
Block a user