From patchwork Fri Mar 18 19:18:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 11388 Received: (qmail 82309 invoked by alias); 18 Mar 2016 19:18:56 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 82239 invoked by uid 89); 18 Mar 2016 19:18:55 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=retried, consistently, 1647, Hx-languages-length:2622 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 18 Mar 2016 19:18:52 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id C275E80E42 for ; Fri, 18 Mar 2016 19:18:50 +0000 (UTC) Received: from cascais.lan (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u2IJIYkG028091 for ; Fri, 18 Mar 2016 15:18:50 -0400 From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 18/30] Fix inconsistent handling of EINTR in ser-*.c backends Date: Fri, 18 Mar 2016 19:18:22 +0000 Message-Id: <1458328714-4938-19-git-send-email-palves@redhat.com> In-Reply-To: <1458328714-4938-1-git-send-email-palves@redhat.com> References: <1458328714-4938-1-git-send-email-palves@redhat.com> - 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: yyyy-mm-dd Pedro Alves * 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. --- gdb/ser-base.c | 20 +++++++++++++++++--- gdb/ser-unix.c | 12 +----------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/gdb/ser-base.c b/gdb/ser-base.c index 21d52cd..25af66a 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; } diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c index c54b2e1..562e98b 100644 --- a/gdb/ser-unix.c +++ b/gdb/ser-unix.c @@ -1002,21 +1002,11 @@ when debugging using remote targets."), int ser_unix_read_prim (struct serial *scb, size_t count) { - int status; - - while (1) - { - status = read (scb->fd, scb->buf, count); - if (status != -1 || errno != EINTR) - break; - } - return status; + return read (scb->fd, scb->buf, count); } int ser_unix_write_prim (struct serial *scb, const void *buf, size_t len) { - /* ??? Historically, GDB has not retried calls to "write" that - result in EINTR. */ return write (scb->fd, buf, len); }