Flawed patch to capture inferior output

Tom Tromey tromey@redhat.com
Wed Nov 7 15:16:00 GMT 2001


>>>>> "Chris" == Christopher Faylor <cgf@redhat.com> writes:

Chris> I did a little digging and found that the GNU inetutils package
Chris> has a generic implementation of openpty() and forkpty().  I
Chris> don't know if they are completely portable.  They do work on
Chris> Cygwin and Linux for sure, though.

Wow, cool.

I've appended the next generation of my "inferior output" patch.  It
doesn't yet use the portable openpty -- it just checks and uses
whatever openpty is available on the platform (if any).

With this change inferior output shows up in the Insight console and
is correctly (not-) buffered by the inferior's stdio.  It's very nice
to use.

Making this use the inetutils openpty will have to wait until my next
spare gdb hacking day.  Meanwhile, is it worth submitting this for
approval?  Or should I just hold off?  I think this patch is a
definite improvement, even if it isn't perfect.  It certainly makes
debugging with Insight more friendly on Linux.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* config.in: Rebuilt.
	* configure: Rebuilt.
	* configure.in: Check for pty.h, -lutil, and openpty().

Index: configure.in
===================================================================
RCS file: /cvs/src/src/gdb/configure.in,v
retrieving revision 1.74
diff -u -r1.74 configure.in
--- configure.in 2001/11/05 23:54:49 1.74
+++ configure.in 2001/11/07 23:06:11
@@ -126,7 +126,8 @@
 	time.h sys/file.h sys/ioctl.h sys/user.h sys/fault.h sys/syscall.h \
 	dirent.h sys/ndir.h sys/dir.h ndir.h \
 	curses.h ncurses.h \
-	poll.h sys/poll.h)
+	poll.h sys/poll.h \
+	pty.h)
 AC_HEADER_STAT
 
 AC_C_CONST
@@ -825,7 +826,6 @@
 esac
 AC_SUBST(SER_HARDWIRE)
 
-
 dnl Figure out which term library to use.
 if test x$gdb_host = xgo32; then
   TERM_LIB=
@@ -1052,6 +1052,14 @@
 	      WIN32LDAPP="-Wl,--subsystem,console"
 	      CONFIG_OBS="${CONFIG_OBS} gdbres.o"
 	   fi
+
+	   dnl See if we have openpty.  It might be in libutil.
+	   AC_CHECK_FUNCS(openpty, ,[
+	     AC_CHECK_LIB(util, openpty, [
+	       GDBTKLIBS="$GDBTKLIBS -lutil"
+	       AC_DEFINE([HAVE_OPENPTY])
+	     ])
+	   ])
 	fi
     fi
 fi
Index: gdbtk/ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* library/interface.tcl (gdbtk_init_read_from_inferior): New proc.
	(gdbtk_read_from_inferior): New proc.
	* generic/gdbtk.c (gdbtk_redirect_io): New function.
	(gdbtk_init): Call it.
	Include <pty.h> if available.

Index: gdbtk/generic/gdbtk.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbtk/generic/gdbtk.c,v
retrieving revision 1.23
diff -u -r1.23 gdbtk.c
--- gdbtk/generic/gdbtk.c 2001/10/04 15:01:35 1.23
+++ gdbtk/generic/gdbtk.c 2001/11/07 23:06:14
@@ -66,6 +66,10 @@
 #include <sys/cygwin.h>		/* for cygwin32_attach_handle_to_fd */
 #endif
 
+#ifdef HAVE_PTY_H
+#include <pty.h>
+#endif
+
 extern void _initialize_gdbtk (void);
 
 /* For unix natives, we use a timer to periodically keep the gui alive.
@@ -347,6 +351,40 @@
 }
 
 
+/* Change gdb's own file descriptors so that the inferior will not try
+   to use gdb's controlling terminal for I/O.  */
+static void
+gdbtk_redirect_io ()
+{
+#ifdef HAVE_OPENPTY
+  /* We use openpty to make sure the inferior has a pty.  This way the
+     inferior's stdio buffering won't be messed up, as it would be
+     with a mere pipe.  */
+  Tcl_Channel inf_out;
+  int master, slave;
+  char buffer[256];
+
+  /* Make a pty for the child, and then make sure all the child's
+     standard file descriptors point to the pty.  */
+  if (openpty (&master, &slave, NULL, NULL, NULL) == -1
+      || dup2 (slave, 0) < 0
+      || dup2 (slave, 1) < 0
+      || dup2 (slave, 2) < 0
+      || close (slave) < 0)
+    error (safe_strerror (errno));
+
+  /* FIXME: mark MASTER as close-on-exec.  */
+
+  /* Register the master end of the pty with Tcl, and arrange for data
+     sent down across to be displayed sensibly.  */
+  inf_out = Tcl_MakeFileChannel ((ClientData) master, TCL_READABLE);
+  Tcl_RegisterChannel (gdbtk_interp, inf_out);
+  sprintf (buffer, "gdbtk_init_read_from_inferior %s",
+	   Tcl_GetChannelName (inf_out));
+  Tcl_GlobalEval (gdbtk_interp, buffer);
+#endif
+}
+
 /* Initialize gdbtk.  This involves creating a Tcl interpreter,
  * defining all the Tcl commands that the GUI will use, pointing
  * all the gdb "hooks" to the correct functions,
@@ -655,6 +693,7 @@
       }
   }
 
+  gdbtk_redirect_io ();
 
   /* Now source in the filename provided by the --tclcommand option.
      This is mostly used for the gdbtk testsuite... */
Index: gdbtk/library/interface.tcl
===================================================================
RCS file: /cvs/src/src/gdb/gdbtk/library/interface.tcl,v
retrieving revision 1.31
diff -u -r1.31 interface.tcl
--- gdbtk/library/interface.tcl 2001/10/28 20:08:38 1.31
+++ gdbtk/library/interface.tcl 2001/11/07 23:06:16
@@ -1761,3 +1761,20 @@
   GDBEventHandler::dispatch $e
   delete object $e
 }
+
+# This is the file event handler for the inferior's output channel.
+proc gdbtk_read_from_inferior {file} {
+  # We ignore EOF because we know we will never hit it.
+  set output [read $file]
+  set cList [ManagedWin::find Console]
+  if {[llength $cList] > 0} {
+    [lindex $cList 0] insert $output
+  }
+}
+
+# This might be run at startup; if so then we arrange to read from the
+# pipe and display the output somewhere.
+proc gdbtk_init_read_from_inferior {file} {
+  fconfigure $file -blocking false -buffering none
+  fileevent $file readable [list gdbtk_read_from_inferior $file]
+}



More information about the Insight mailing list