From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.baldwin.cx (bigwig.baldwin.cx [IPv6:2607:f138:0:13::2]) by sourceware.org (Postfix) with ESMTPS id 9A5703858400 for ; Sat, 27 Nov 2021 01:15:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 9A5703858400 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=FreeBSD.org Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=FreeBSD.org Received: from gimli.baldwin.net (c-98-35-133-24.hsd1.ca.comcast.net [98.35.133.24]) by mail.baldwin.cx (Postfix) with ESMTPSA id EC5241A84C6B for ; Fri, 26 Nov 2021 20:15:11 -0500 (EST) From: John Baldwin To: gdb-patches@sourceware.org Subject: [PATCH v3 14/14] inf-ptrace: Add an event_pipe to be used for async mode in subclasses. Date: Fri, 26 Nov 2021 17:14:53 -0800 Message-Id: <20211127011453.74487-15-jhb@FreeBSD.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20211127011453.74487-1-jhb@FreeBSD.org> References: <20211127011453.74487-1-jhb@FreeBSD.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.6.4 (mail.baldwin.cx [0.0.0.0]); Fri, 26 Nov 2021 20:15:12 -0500 (EST) X-Virus-Scanned: clamav-milter 0.103.1 at mail.baldwin.cx X-Virus-Status: Clean X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, FORGED_SPF_HELO, GIT_PATCH_0, KAM_DMARC_STATUS, KHOP_HELO_FCRDNS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 27 Nov 2021 01:15:14 -0000 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. --- gdb/fbsd-nat.c | 50 ++++--------------- gdb/fbsd-nat.h | 4 -- gdb/inf-ptrace.c | 15 ++++++ gdb/inf-ptrace.h | 30 ++++++++++++ gdb/linux-nat.c | 123 +++++++++-------------------------------------- gdb/linux-nat.h | 4 -- 6 files changed, 78 insertions(+), 148 deletions(-) diff --git a/gdb/fbsd-nat.c b/gdb/fbsd-nat.c index 063525b1aa2..71985fb4160 100644 --- a/gdb/fbsd-nat.c +++ b/gdb/fbsd-nat.c @@ -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 (), diff --git a/gdb/fbsd-nat.h b/gdb/fbsd-nat.h index 7dd47cf82c0..9c76b187555 100644 --- a/gdb/fbsd-nat.h +++ b/gdb/fbsd-nat.h @@ -67,13 +67,9 @@ class fbsd_nat_target : public inf_ptrace_target 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; } diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c index 1cec88d97aa..ddb0d987be9 100644 --- a/gdb/inf-ptrace.c +++ b/gdb/inf-ptrace.c @@ -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 () {} @@ -532,3 +535,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 (); +} diff --git a/gdb/inf-ptrace.h b/gdb/inf-ptrace.h index 8aded9b60db..997b8014440 100644 --- a/gdb/inf-ptrace.h +++ b/gdb/inf-ptrace.h @@ -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,9 +60,36 @@ 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); + +private: + static event_pipe m_event_pipe; }; #ifndef __NetBSD__ diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index e5376a63dac..a7a14b7e252 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -48,7 +48,6 @@ #include /* for O_RDONLY */ #include "inf-loop.h" #include "gdbsupport/event-loop.h" -#include "gdbsupport/event-pipe.h" #include "event-top.h" #include #include @@ -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" @@ -217,32 +217,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); @@ -4048,14 +4022,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 @@ -4107,10 +4073,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; } @@ -4123,67 +4090,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 @@ -4231,16 +4166,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, diff --git a/gdb/linux-nat.h b/gdb/linux-nat.h index 95e26b7ee46..243d9a3f636 100644 --- a/gdb/linux-nat.h +++ b/gdb/linux-nat.h @@ -83,16 +83,12 @@ class linux_nat_target : public inf_ptrace_target 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; -- 2.33.0