[PING,v2] gdb: add a file event mask parameter to add_file_handler

Message ID 20221001132349.76809-1-patrick@monnerat.net
State New
Headers
Series [PING,v2] gdb: add a file event mask parameter to add_file_handler |

Commit Message

Patrick Monnerat Oct. 1, 2022, 1:23 p.m. UTC
  Tcl/Tk (used as the Insight GUI) delegates event handling to gdb and
requires file events monitoring to be masked with READ/WRITE/EXCEPTION
flags.

Currently, gdb only uses read events, but an unused and incomplete
provision exists for such flags.

This patch adds an event mask parameter to add_file_handler, allowing
to monitor non-read file events. Its value is always given as ored-in gdb
flags, whether effectively using poll or select. This parameter defaults to
GDB_READABLE | GDB_EXCEPTION, resulting in no change for existing calls.

To unify the semantics between select and poll, POLLRDHUP
(HANGUP-sensitiveness) is also included in read events on platforms
supporting it. This is the only change in this patch that may affect
bare gdb.

This patch benefits to Insight: the latter itself does not use non-read
file events. However these must be supported for Tcl/Tk internals.

It should be noted that gdb does not support write events on the mingw
platform but checks this condition with gdb_assert. This patch does not
change this.

Flags GDB_READABLE, GDB_WRITABLE and GDB_EXCEPTION are now made globally
available through the inclusion of event-loop.h.
---
 gdbsupport/event-loop.cc | 43 +++++++++++++++++++++++-----------------
 gdbsupport/event-loop.h  | 11 ++++++++--
 2 files changed, 34 insertions(+), 20 deletions(-)
  

Patch

diff --git a/gdbsupport/event-loop.cc b/gdbsupport/event-loop.cc
index 941885529f1..45990fbdd9b 100644
--- a/gdbsupport/event-loop.cc
+++ b/gdbsupport/event-loop.cc
@@ -28,6 +28,11 @@ 
 #elif defined (HAVE_SYS_POLL_H)
 #include <sys/poll.h>
 #endif
+#if defined (POLLRDHUP)
+#define POLL_HANGUP POLLRDHUP
+#else
+#define POLL_HANGUP 0
+#endif
 #endif
 
 #include <sys/types.h>
@@ -40,13 +45,6 @@ 
 
 debug_event_loop_kind debug_event_loop;
 
-/* Tell create_file_handler what events we are interested in.
-   This is used by the select version of the event loop.  */
-
-#define GDB_READABLE	(1<<1)
-#define GDB_WRITABLE	(1<<2)
-#define GDB_EXCEPTION	(1<<3)
-
 /* Information about each file descriptor we register with the event
    loop.  */
 
@@ -269,8 +267,14 @@  gdb_do_one_event (int mstimeout)
 
 void
 add_file_handler (int fd, handler_func *proc, gdb_client_data client_data,
-		  std::string &&name, bool is_ui)
+		  std::string &&name, bool is_ui, int mask)
 {
+  /* If no event is monitored, remove an existing handler. */
+  if ((mask & (GDB_READABLE | GDB_WRITABLE | GDB_EXCEPTION)) == 0) {
+    delete_file_handler (fd);
+    return;
+  }
+
 #ifdef HAVE_POLL
   if (use_poll)
     {
@@ -282,25 +286,28 @@  add_file_handler (int fd, handler_func *proc, gdb_client_data client_data,
 	 On m68k-motorola-sysv, tty's are not stream-based and not
 	 `poll'able.  */
       fds.fd = fd;
-      fds.events = POLLIN;
+      fds.events = 0;
+      if (mask & GDB_READABLE)
+	fds.events |= POLLIN | POLL_HANGUP;
+      if (mask & GDB_WRITABLE)
+	fds.events |= POLLOUT;
+      if (mask & GDB_EXCEPTION)
+	fds.events |= POLLPRI;
       if (poll (&fds, 1, 0) == 1 && (fds.revents & POLLNVAL))
 	use_poll = false;
+      else
+	create_file_handler (fd, fds.events, proc, client_data,
+			     std::move (name), is_ui);
     }
-  if (use_poll)
-    {
-      create_file_handler (fd, POLLIN, proc, client_data, std::move (name),
-			   is_ui);
-    }
-  else
+  if (!use_poll)
 #endif /* HAVE_POLL */
-    create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION,
-			 proc, client_data, std::move (name), is_ui);
+    create_file_handler (fd, mask, proc, client_data, std::move (name), is_ui);
 }
 
 /* Helper for add_file_handler.
 
    For the poll case, MASK is a combination (OR) of POLLIN,
-   POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM, POLLWRBAND:
+   POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM, POLLWRBAND, POLLRDHUP:
    these are the events we are interested in.  If any of them occurs,
    proc should be called.
 
diff --git a/gdbsupport/event-loop.h b/gdbsupport/event-loop.h
index c82493e9bdf..8c1f831af27 100644
--- a/gdbsupport/event-loop.h
+++ b/gdbsupport/event-loop.h
@@ -70,11 +70,17 @@ 
 
    Corollary tasks are the creation and deletion of event sources.  */
 
+/* Tell add_file_handler what events we are interested in. */
+
+#define GDB_READABLE	(1<<1)
+#define GDB_WRITABLE	(1<<2)
+#define GDB_EXCEPTION	(1<<3)
+
 typedef void *gdb_client_data;
 typedef void (handler_func) (int, gdb_client_data);
 typedef void (timer_handler_func) (gdb_client_data);
 
-/* Exported functions from event-loop.c */
+/* Exported functions from event-loop.cc */
 
 extern int gdb_do_one_event (int mstimeout = -1);
 extern void delete_file_handler (int fd);
@@ -90,7 +96,8 @@  extern void delete_file_handler (int fd);
 
 extern void add_file_handler (int fd, handler_func *proc,
 			      gdb_client_data client_data,
-			      std::string &&name, bool is_ui = false);
+			      std::string &&name, bool is_ui = false,
+			      int mask = GDB_READABLE | GDB_EXCEPTION);
 
 extern int create_timer (int milliseconds, 
 			 timer_handler_func *proc,