diff options
author | Pedro Alves <palves@redhat.com> | 2016-04-12 16:49:31 +0100 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2016-04-12 16:57:33 +0100 |
commit | 75ee59252d49dffb017905125cdf826f89a6baf9 (patch) | |
tree | 0b083ce32e0dd3fba3fe169f3fbc15a0232dde81 /gdb/ser-base.c | |
parent | 93692b589dc7017d5a2fbdffdfad5f84f597d8f1 (diff) | |
download | binutils-gdb-75ee59252d49dffb017905125cdf826f89a6baf9.tar.gz |
Fix inconsistent handling of EINTR in ser-*.c backends
- If serial->write_prim returns EINTR, ser_bas_write returns it to the
caller. This just looks wrong to me -- part of the output may have
already been sent, and there's no way for the caller to know that,
and thus no way for a caller to handle a partial write correctly.
- While ser-unix.c:ser_unix_read_prim retries on EINTR,
ser-tcp.c:net_read_prim does not.
This commit moves EINTR handling to the ser_base_write and
ser_base_readchar level, so all serial backends (at least those that
use it) end up handling EINTR consistently.
gdb/ChangeLog:
2016-04-12 Pedro Alves <palves@redhat.com>
* ser-base.c (fd_event): Retry read_prim on EINTR.
(do_ser_base_readchar): Retry read_prim on EINTR.
(ser_base_write): Retry write_prim on EINTR.
* ser-unix.c (ser_unix_read_prim): Don't retry on EINTR here.
(ser_unix_write_prim): Remove comment.
Diffstat (limited to 'gdb/ser-base.c')
-rw-r--r-- | gdb/ser-base.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/gdb/ser-base.c b/gdb/ser-base.c index 21d52cd928e..25af66a91f6 100644 --- a/gdb/ser-base.c +++ b/gdb/ser-base.c @@ -164,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; @@ -358,7 +364,11 @@ do_ser_base_readchar (struct serial *scb, int timeout) 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) { @@ -448,7 +458,11 @@ ser_base_write (struct serial *scb, const void *buf, size_t count) cc = scb->ops->write_prim (scb, str, count); if (cc < 0) - return 1; + { + if (errno == EINTR) + continue; + return 1; + } count -= cc; str += cc; } |