X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fser-base.c;h=c51be07e0fcfdb74412a746e80ba0c6e45627182;hb=0154d99053a95392380cd4629a89b0ac46df3737;hp=2f12dfcdc172fc1a0c1e550473a12b24145fa431;hpb=ddefb60ff89becf2b18d0cf7930358320c6ec0e6;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ser-base.c b/gdb/ser-base.c index 2f12dfcdc1..c51be07e0f 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-2016 Free Software Foundation, Inc. This file is part of GDB. @@ -24,8 +23,7 @@ #include "event-loop.h" #include "gdb_select.h" -#include "gdb_string.h" -#include +#include "gdb_sys_time.h" #ifdef USE_WIN32API #include #endif @@ -155,7 +153,7 @@ run_async_handler_and_reschedule (struct serial *scb) static void fd_event (int error, void *context) { - struct serial *scb = context; + struct serial *scb = (struct serial *) context; if (error != 0) { scb->bufcnt = SERIAL_ERROR; @@ -166,7 +164,13 @@ fd_event (int error, void *context) pull characters out of the buffer. See also generic_readchar(). */ int nr; - nr = scb->ops->read_prim (scb, BUFSIZ); + + do + { + nr = scb->ops->read_prim (scb, BUFSIZ); + } + while (nr < 0 && errno == EINTR); + if (nr == 0) { scb->bufcnt = SERIAL_EOF; @@ -192,7 +196,7 @@ fd_event (int error, void *context) static void push_event (void *context) { - struct serial *scb = context; + struct serial *scb = (struct serial *) context; scb->async_state = NOTHING_SCHEDULED; /* Timers are one-off */ run_async_handler_and_reschedule (scb); @@ -209,6 +213,7 @@ ser_base_wait_for (struct serial *scb, int timeout) int numfds; struct timeval tv; fd_set readfds, exceptfds; + int nfds; /* NOTE: Some OS's can scramble the READFDS when the select() call fails (ex the kernel with Red Hat 5.2). Initialize all @@ -222,10 +227,13 @@ ser_base_wait_for (struct serial *scb, int timeout) FD_SET (scb->fd, &readfds); FD_SET (scb->fd, &exceptfds); + QUIT; + + nfds = scb->fd + 1; if (timeout >= 0) - numfds = gdb_select (scb->fd + 1, &readfds, 0, &exceptfds, &tv); + numfds = interruptible_select (nfds, &readfds, 0, &exceptfds, &tv); else - numfds = gdb_select (scb->fd + 1, &readfds, 0, &exceptfds, 0); + numfds = interruptible_select (nfds, &readfds, 0, &exceptfds, 0); if (numfds <= 0) { @@ -242,6 +250,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,12 +358,21 @@ 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) return status; - status = scb->ops->read_prim (scb, BUFSIZ); + do + { + status = scb->ops->read_prim (scb, BUFSIZ); + } + while (status < 0 && errno == EINTR); if (status <= 0) { @@ -362,54 +437,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 +452,24 @@ 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 = (const char *) buf; int cc; - while (len > 0) + while (count > 0) { - cc = scb->ops->write_prim (scb, str, len); + QUIT; + + cc = scb->ops->write_prim (scb, str, count); if (cc < 0) - return 1; - len -= cc; + { + if (errno == EINTR) + continue; + return 1; + } + count -= cc; str += cc; } return 0; @@ -479,14 +516,14 @@ serial_ttystate ser_base_get_tty_state (struct serial *scb) { /* Allocate a dummy. */ - return (serial_ttystate) XMALLOC (int); + return (serial_ttystate) XNEW (int); } serial_ttystate ser_base_copy_tty_state (struct serial *scb, serial_ttystate ttystate) { /* Allocate another dummy. */ - return (serial_ttystate) XMALLOC (int); + return (serial_ttystate) XNEW (int); } int @@ -524,6 +561,14 @@ ser_base_setstopbits (struct serial *scb, int num) return 0; /* Never fails! */ } +/* Implement the "setparity" serial_ops callback. */ + +int +ser_base_setparity (struct serial *scb, int parity) +{ + return 0; /* Never fails! */ +} + /* Put the SERIAL device into/out-of ASYNC mode. */ void