Pass stderr of program run with "target remote |"
via gdb_stderr. * serial.c (serial_open): Set error_fd to -1. * serial.h (struct serial): New field error_fd. (struct serial_opts): New field avail. * ser-pipe.c (pipe_open): Create another pair of sockets. Pass stderr to gdb. * ser-mingw.c (pipe_windows_open): Pass PEX_STDERR_TO_PIPE to pex_run. Initialize sd->error_fd. (pipe_avail): New. (_initialize_ser_windows): Hook pipe_avail. * ser-base.c (generic_readchar): Check if there's anything in stderr channel and route that to gdb_stderr.
This commit is contained in:
parent
1edf24da1a
commit
65cc4390f1
@ -1,3 +1,20 @@
|
||||
2007-04-08 Vladimir Prus <vladimir@codesourcery.com>
|
||||
|
||||
Pass stderr of program run with "target remote |"
|
||||
via gdb_stderr.
|
||||
* serial.c (serial_open): Set error_fd to -1.
|
||||
* serial.h (struct serial): New field error_fd.
|
||||
(struct serial_opts): New field avail.
|
||||
* ser-pipe.c (pipe_open): Create another pair
|
||||
of sockets. Pass stderr to gdb.
|
||||
* ser-mingw.c (pipe_windows_open): Pass
|
||||
PEX_STDERR_TO_PIPE to pex_run. Initialize
|
||||
sd->error_fd.
|
||||
(pipe_avail): New.
|
||||
(_initialize_ser_windows): Hook pipe_avail.
|
||||
* ser-base.c (generic_readchar): Check if there's
|
||||
anything in stderr channel and route that to gdb_stderr.
|
||||
|
||||
2007-04-03 Pedro Alves <pedro_alves@portugalmail.pt>
|
||||
|
||||
* dbxread.c (read_ofile_symtab): Move current_objfile
|
||||
|
@ -343,6 +343,48 @@ generic_readchar (struct serial *scb, int timeout,
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Read any error output we might have. */
|
||||
if (scb->error_fd != -1)
|
||||
{
|
||||
ssize_t s;
|
||||
char buf[81];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char *current;
|
||||
char *newline;
|
||||
int to_read = 80;
|
||||
|
||||
int num_bytes = -1;
|
||||
if (scb->ops->avail)
|
||||
num_bytes = (scb->ops->avail)(scb, scb->error_fd);
|
||||
if (num_bytes != -1)
|
||||
to_read = (num_bytes < to_read) ? num_bytes : to_read;
|
||||
|
||||
if (to_read == 0)
|
||||
break;
|
||||
|
||||
s = read (scb->error_fd, &buf, to_read);
|
||||
if (s == -1)
|
||||
break;
|
||||
|
||||
/* In theory, embedded newlines are not a problem.
|
||||
But for MI, we want each output line to have just
|
||||
one newline for legibility. So output things
|
||||
in newline chunks. */
|
||||
buf[s] = '\0';
|
||||
current = buf;
|
||||
while ((newline = strstr (current, "\n")) != NULL)
|
||||
{
|
||||
*newline = '\0';
|
||||
fputs_unfiltered (current, gdb_stderr);
|
||||
fputs_unfiltered ("\n", gdb_stderr);
|
||||
current = newline + 1;
|
||||
}
|
||||
fputs_unfiltered (current, gdb_stderr);
|
||||
}
|
||||
}
|
||||
|
||||
reschedule (scb);
|
||||
return ch;
|
||||
}
|
||||
|
@ -697,6 +697,7 @@ static int
|
||||
pipe_windows_open (struct serial *scb, const char *name)
|
||||
{
|
||||
struct pipe_state *ps;
|
||||
FILE *pex_stderr;
|
||||
|
||||
char **argv = buildargv (name);
|
||||
struct cleanup *back_to = make_cleanup_freeargv (argv);
|
||||
@ -717,7 +718,8 @@ pipe_windows_open (struct serial *scb, const char *name)
|
||||
{
|
||||
int err;
|
||||
const char *err_msg
|
||||
= pex_run (ps->pex, PEX_SEARCH | PEX_BINARY_INPUT | PEX_BINARY_OUTPUT,
|
||||
= pex_run (ps->pex, PEX_SEARCH | PEX_BINARY_INPUT | PEX_BINARY_OUTPUT
|
||||
| PEX_STDERR_TO_PIPE,
|
||||
argv[0], argv, NULL, NULL,
|
||||
&err);
|
||||
|
||||
@ -739,8 +741,13 @@ pipe_windows_open (struct serial *scb, const char *name)
|
||||
ps->output = pex_read_output (ps->pex, 1);
|
||||
if (! ps->output)
|
||||
goto fail;
|
||||
|
||||
scb->fd = fileno (ps->output);
|
||||
|
||||
pex_stderr = pex_read_err (ps->pex, 1);
|
||||
if (! pex_stderr)
|
||||
goto fail;
|
||||
scb->error_fd = fileno (pex_stderr);
|
||||
|
||||
scb->state = (void *) ps;
|
||||
|
||||
discard_cleanups (back_to);
|
||||
@ -865,6 +872,17 @@ pipe_done_wait_handle (struct serial *scb)
|
||||
WaitForSingleObject (ps->wait.have_stopped, INFINITE);
|
||||
}
|
||||
|
||||
static int
|
||||
pipe_avail (struct serial *scb, int fd)
|
||||
{
|
||||
HANDLE h = (HANDLE) _get_osfhandle (fd);
|
||||
DWORD numBytes;
|
||||
BOOL r = PeekNamedPipe (h, NULL, 0, NULL, &numBytes, NULL);
|
||||
if (r == FALSE)
|
||||
numBytes = 0;
|
||||
return numBytes;
|
||||
}
|
||||
|
||||
struct net_windows_state
|
||||
{
|
||||
HANDLE read_event;
|
||||
@ -1164,6 +1182,7 @@ _initialize_ser_windows (void)
|
||||
ops->write_prim = pipe_windows_write;
|
||||
ops->wait_handle = pipe_wait_handle;
|
||||
ops->done_wait_handle = pipe_done_wait_handle;
|
||||
ops->avail = pipe_avail;
|
||||
|
||||
serial_add_interface (ops);
|
||||
|
||||
|
@ -62,9 +62,12 @@ pipe_open (struct serial *scb, const char *name)
|
||||
* published in UNIX Review, Vol. 6, No. 8.
|
||||
*/
|
||||
int pdes[2];
|
||||
int err_pdes[2];
|
||||
int pid;
|
||||
if (socketpair (AF_UNIX, SOCK_STREAM, 0, pdes) < 0)
|
||||
return -1;
|
||||
if (socketpair (AF_UNIX, SOCK_STREAM, 0, err_pdes) < 0)
|
||||
return -1;
|
||||
|
||||
/* Create the child process to run the command in. Note that the
|
||||
apparent call to vfork() below *might* actually be a call to
|
||||
@ -77,9 +80,18 @@ pipe_open (struct serial *scb, const char *name)
|
||||
{
|
||||
close (pdes[0]);
|
||||
close (pdes[1]);
|
||||
close (err_pdes[0]);
|
||||
close (err_pdes[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl (err_pdes[0], F_SETFL, O_NONBLOCK) == -1)
|
||||
{
|
||||
close (err_pdes[0]);
|
||||
close (err_pdes[1]);
|
||||
err_pdes[0] = err_pdes[1] = -1;
|
||||
}
|
||||
|
||||
/* Child. */
|
||||
if (pid == 0)
|
||||
{
|
||||
@ -91,6 +103,13 @@ pipe_open (struct serial *scb, const char *name)
|
||||
close (pdes[1]);
|
||||
}
|
||||
dup2 (STDOUT_FILENO, STDIN_FILENO);
|
||||
|
||||
if (err_pdes[0] != -1)
|
||||
{
|
||||
close (err_pdes[0]);
|
||||
dup2 (err_pdes[1], STDERR_FILENO);
|
||||
close (err_pdes[1]);
|
||||
}
|
||||
#if 0
|
||||
/* close any stray FD's - FIXME - how? */
|
||||
/* POSIX.2 B.3.2.2 "popen() shall ensure that any streams
|
||||
@ -109,6 +128,7 @@ pipe_open (struct serial *scb, const char *name)
|
||||
state = XMALLOC (struct pipe_state);
|
||||
state->pid = pid;
|
||||
scb->fd = pdes[0];
|
||||
scb->error_fd = err_pdes[0];
|
||||
scb->state = state;
|
||||
|
||||
/* If we don't do this, GDB simply exits when the remote side dies. */
|
||||
|
@ -211,6 +211,7 @@ serial_open (const char *name)
|
||||
|
||||
scb->bufcnt = 0;
|
||||
scb->bufp = scb->buf;
|
||||
scb->error_fd = -1;
|
||||
|
||||
if (scb->ops->open (scb, open_name))
|
||||
{
|
||||
|
10
gdb/serial.h
10
gdb/serial.h
@ -191,6 +191,11 @@ extern int serial_debug_p (struct serial *scb);
|
||||
struct serial
|
||||
{
|
||||
int fd; /* File descriptor */
|
||||
/* File descriptor for a separate error stream that should be
|
||||
immediately forwarded to gdb_stderr. This may be -1.
|
||||
If != -1, this descriptor should be non-blocking or
|
||||
ops->avail should be non-NULL. */
|
||||
int error_fd;
|
||||
struct serial_ops *ops; /* Function vector */
|
||||
void *state; /* Local context info for open FD */
|
||||
serial_ttystate ttystate; /* Not used (yet) */
|
||||
@ -246,6 +251,11 @@ struct serial_ops
|
||||
/* Perform a low-level write operation, writing (at most) COUNT
|
||||
bytes from BUF. */
|
||||
int (*write_prim)(struct serial *scb, const void *buf, size_t count);
|
||||
/* Return that number of bytes that can be read from FD
|
||||
without blocking. Return value of -1 means that the
|
||||
the read will not block even if less that requested bytes
|
||||
are available. */
|
||||
int (*avail)(struct serial *scb, int fd);
|
||||
|
||||
#ifdef USE_WIN32API
|
||||
/* Return a handle to wait on, indicating available data from SCB
|
||||
|
Loading…
Reference in New Issue
Block a user