Index: gdb/ser-base.c |
diff --git a/gdb/ser-base.c b/gdb/ser-base.c |
index 2f12dfcdc172fc1a0c1e550473a12b24145fa431..d07dcf3e4809d8610498ddb07342191f46ccb765 100644 |
--- a/gdb/ser-base.c |
+++ b/gdb/ser-base.c |
@@ -1,7 +1,6 @@ |
/* Generic serial interface functions. |
- Copyright (C) 1992-1996, 1998-2001, 2003-2012 Free Software |
- Foundation, Inc. |
+ Copyright (C) 1992-2013 Free Software Foundation, Inc. |
This file is part of GDB. |
@@ -24,7 +23,8 @@ |
#include "event-loop.h" |
#include "gdb_select.h" |
-#include "gdb_string.h" |
+#include <string.h> |
+#include "gdb_assert.h" |
#include <sys/time.h> |
#ifdef USE_WIN32API |
#include <winsock2.h> |
@@ -242,6 +242,64 @@ ser_base_wait_for (struct serial *scb, int timeout) |
} |
} |
+/* Read any error output we might have. */ |
+ |
+static void |
+ser_base_read_error_fd (struct serial *scb, int close_fd) |
+{ |
+ if (scb->error_fd != -1) |
+ { |
+ ssize_t s; |
+ char buf[GDB_MI_MSG_WIDTH + 1]; |
+ |
+ for (;;) |
+ { |
+ char *current; |
+ char *newline; |
+ int to_read = GDB_MI_MSG_WIDTH; |
+ 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) || (s == 0 && !close_fd)) |
+ break; |
+ |
+ if (s == 0 && close_fd) |
+ { |
+ /* End of file. */ |
+ close (scb->error_fd); |
+ scb->error_fd = -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. */ |
+ gdb_assert (s > 0 && s <= GDB_MI_MSG_WIDTH); |
+ 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); |
+ } |
+ } |
+} |
+ |
/* Read a character with user-specified timeout. TIMEOUT is number of seconds |
to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns |
char if successful. Returns -2 if timeout expired, EOF if line dropped |
@@ -292,6 +350,11 @@ do_ser_base_readchar (struct serial *scb, int timeout) |
status = SERIAL_TIMEOUT; |
break; |
} |
+ |
+ /* We also need to check and consume the stderr because it could |
+ come before the stdout for some stubs. If we just sit and wait |
+ for stdout, we would hit a deadlock for that case. */ |
+ ser_base_read_error_fd (scb, 0); |
} |
if (status < 0) |
@@ -362,54 +425,9 @@ 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; |
- if (s == 0) |
- { |
- /* EOF */ |
- close (scb->error_fd); |
- scb->error_fd = -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); |
- } |
- } |
+ /* Read any error output we might have. */ |
+ ser_base_read_error_fd (scb, 1); |
reschedule (scb); |
return ch; |
@@ -422,17 +440,18 @@ ser_base_readchar (struct serial *scb, int timeout) |
} |
int |
-ser_base_write (struct serial *scb, const char *str, int len) |
+ser_base_write (struct serial *scb, const void *buf, size_t count) |
{ |
+ const char *str = buf; |
int cc; |
- while (len > 0) |
+ while (count > 0) |
{ |
- cc = scb->ops->write_prim (scb, str, len); |
+ cc = scb->ops->write_prim (scb, str, count); |
if (cc < 0) |
return 1; |
- len -= cc; |
+ count -= cc; |
str += cc; |
} |
return 0; |