This is the mail archive of the insight@sources.redhat.com mailing list for the Insight project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Flawed patch to capture inferior output


Today I wrote a simple patch that arranges for the inferior's stdout
and stderr to end up in the Console window.  This patch also makes it
possible to run insight in the background -- something I've wanted for
a long time.

Unfortunately this patch has an undesirable side effect.  Since the
inferior's stdout/stderr are now pipes and not terminals, by default
they are given full, and not line, buffering (at least, that is
consistent with what I see when debugging).  This makes this feature
much less useful, as output from the inferior doesn't show up until it
is flushed.

One way to fix this flaw would be to change gdbtk_redirect_io to
create a new terminal and then use the slave side as the inferior's
new stdout/stderr.  This looks hard enough that I'm not going to
attempt it.

Nevertheless, here's my patch for the record.  Maybe it will be useful
to someone else.

Inferior I/O handling is currently my biggest complaint about
debugging with Insight.  For instance, if you debug a gcc front end
you end up using `debug_tree' a lot.  This prints a tree structure to
stdout.  With Insight this means constant switching between the
console and the xterm where I ran Insight, bleah.  (Of course, for
this particular case I should write a plugin which displays gcc tree
structures in a nicer way -- debug_tree output is ugly.  I wish I had
the time to do that!)

Tom

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.

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/10/06 20:09:00
@@ -347,6 +347,41 @@
 }
 
 
+/* 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 ()
+{
+#ifndef _WIN32
+  /* We only do this on Unix boxes.  */
+  Tcl_Channel inf_out;
+  int infd, outfds[2];
+  char buffer[256];
+
+  /* We make a pipe for stdout+stderr, and we arrange for stdin to
+     come from /dev/null.  If we wanted we could make stdin a pipe and
+     somehow arrange to let the user type directly to the inferior,
+     but for now we don't.  For one thing the user can use the xterm
+     tty code in this scenario.  */
+  if ((infd = open ("/dev/null", O_RDONLY)) < 0
+      || pipe (outfds) < 0
+      || dup2 (infd, 0) < 0
+      || dup2 (outfds[1], 1) < 0
+      || dup2 (outfds[1], 2) < 0
+      || close (outfds[1]) < 0)
+    error (safe_strerror (errno));
+
+  /* Register the read end of the inferior stdout/stderr pipe with
+     Tcl, and arrange for data sent down this pipe to be displayed
+     sensibly.  */
+  inf_out = Tcl_MakeFileChannel ((ClientData) outfds[0], 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 +690,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.30
diff -u -r1.30 interface.tcl
--- gdbtk/library/interface.tcl 2001/10/06 18:10:50 1.30
+++ gdbtk/library/interface.tcl 2001/10/06 20:09:02
@@ -1767,3 +1767,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]
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]