This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb] Fix inconsistent handling of EINTR in ser-*.c backends


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=75ee59252d49dffb017905125cdf826f89a6baf9

commit 75ee59252d49dffb017905125cdf826f89a6baf9
Author: Pedro Alves <palves@redhat.com>
Date:   Tue Apr 12 16:49:31 2016 +0100

    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.

Diff:
---
 gdb/ChangeLog  |  8 ++++++++
 gdb/ser-base.c | 20 +++++++++++++++++---
 gdb/ser-unix.c | 12 +-----------
 3 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ac6c281..8fa4b02 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
 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.
+
+2016-04-12  Pedro Alves  <palves@redhat.com>
+
 	* remote.c (remote_pass_ctrlc): New function.
 	(init_remote_ops): Install it.
 	* target.c (target_terminal_inferior): Pass pending Ctrl-C to the
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);
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]