]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Change serial_send_break and serial_write to throw
authorTom Tromey <tromey@adacore.com>
Wed, 6 Sep 2023 14:33:46 +0000 (08:33 -0600)
committerTom Tromey <tromey@adacore.com>
Mon, 27 Nov 2023 19:55:14 +0000 (12:55 -0700)
This changes serial_send_break and serial_write to throw exceptions
rather than attempt to set errno and return an error indicator.  This
lets us correctly report failures on Windows.

Both functions had to be converted in a single patch because one
implementation of send_break works via write.

This also introduces remote_serial_send_break to handle error checking
when attempting to send a break.  This was previously ignored.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30770

gdb/remote.c
gdb/ser-base.c
gdb/ser-base.h
gdb/ser-mingw.c
gdb/ser-tcp.c
gdb/ser-tcp.h
gdb/ser-uds.c
gdb/ser-unix.c
gdb/serial.c
gdb/serial.h

index 03ebcc6cdfc40b0fc0ce9bd863aa1b1e811d57d8..49c1c96f1e5c04c91cd52f81e06a95f459ab2a3d 100644 (file)
@@ -1264,6 +1264,7 @@ public: /* Remote specific methods.  */
   int readchar (int timeout);
 
   void remote_serial_write (const char *str, int len);
+  void remote_serial_send_break ();
 
   int putpkt (const char *buf);
   int putpkt_binary (const char *buf, int cnt);
@@ -4623,15 +4624,13 @@ remote_target::get_offsets ()
 void
 remote_target::send_interrupt_sequence ()
 {
-  struct remote_state *rs = get_remote_state ();
-
   if (interrupt_sequence_mode == interrupt_sequence_control_c)
     remote_serial_write ("\x03", 1);
   else if (interrupt_sequence_mode == interrupt_sequence_break)
-    serial_send_break (rs->remote_desc);
+    remote_serial_send_break ();
   else if (interrupt_sequence_mode == interrupt_sequence_break_g)
     {
-      serial_send_break (rs->remote_desc);
+      remote_serial_send_break ();
       remote_serial_write ("g", 1);
     }
   else
@@ -4639,7 +4638,6 @@ remote_target::send_interrupt_sequence ()
                    interrupt_sequence_mode);
 }
 
-
 /* If STOP_REPLY is a T stop reply, look for the "thread" register,
    and extract the PTID.  Returns NULL_PTID if not found.  */
 
@@ -9859,16 +9857,42 @@ remote_target::remote_serial_write (const char *str, int len)
 
   rs->got_ctrlc_during_io = 0;
 
-  if (serial_write (rs->remote_desc, str, len))
+  try
     {
-      unpush_and_perror (this, _("Remote communication error.  "
-                                "Target disconnected"));
+      serial_write (rs->remote_desc, str, len);
+    }
+  catch (const gdb_exception_error &ex)
+    {
+      remote_unpush_target (this);
+      throw_error (TARGET_CLOSE_ERROR,
+                  _("Remote communication error.  "
+                    "Target disconnected: %s"),
+                  ex.what ());
     }
 
   if (rs->got_ctrlc_during_io)
     set_quit_flag ();
 }
 
+void
+remote_target::remote_serial_send_break ()
+{
+  struct remote_state *rs = get_remote_state ();
+
+  try
+    {
+      serial_send_break (rs->remote_desc);
+    }
+  catch (const gdb_exception_error &ex)
+    {
+      remote_unpush_target (this);
+      throw_error (TARGET_CLOSE_ERROR,
+                  _("Remote communication error.  "
+                    "Target disconnected: %s"),
+                  ex.what ());
+    }
+}
+
 /* Return a string representing an escaped version of BUF, of len N.
    E.g. \n is converted to \\n, \t to \\t, etc.  */
 
index 072211df1ca69c0a06e6f6087c62abc5a4a9d010..d83003ebf9673ce0769d796857b355f544fad1e9 100644 (file)
@@ -471,7 +471,7 @@ ser_base_readchar (struct serial *scb, int timeout)
   return generic_readchar (scb, timeout, do_ser_base_readchar);
 }
 
-int
+void
 ser_base_write (struct serial *scb, const void *buf, size_t count)
 {
   const char *str = (const char *) buf;
@@ -487,12 +487,11 @@ ser_base_write (struct serial *scb, const void *buf, size_t count)
        {
          if (errno == EINTR)
            continue;
-         return 1;
+         perror_with_name ("error while writing");
        }
       count -= cc;
       str += cc;
     }
-  return 0;
 }
 
 int
@@ -514,10 +513,9 @@ ser_base_flush_input (struct serial *scb)
     return SERIAL_ERROR;
 }
 
-int
+void
 ser_base_send_break (struct serial *scb)
 {
-  return 0;
 }
 
 int
index aeb7a4da333de4846c4d94e734209e3e82f57a62..539ea0620a137096620bbc5cac99d09fae5e33d0 100644 (file)
@@ -30,7 +30,7 @@ extern int generic_readchar (struct serial *scb, int timeout,
                                                 int timeout));
 extern int ser_base_flush_output (struct serial *scb);
 extern int ser_base_flush_input (struct serial *scb);
-extern int ser_base_send_break (struct serial *scb);
+extern void ser_base_send_break (struct serial *scb);
 extern void ser_base_raw (struct serial *scb);
 extern serial_ttystate ser_base_get_tty_state (struct serial *scb);
 extern serial_ttystate ser_base_copy_tty_state (struct serial *scb,
@@ -45,7 +45,7 @@ extern int ser_base_setstopbits (struct serial *scb, int num);
 extern int ser_base_setparity (struct serial *scb, int parity);
 extern int ser_base_drain_output (struct serial *scb);
 
-extern int ser_base_write (struct serial *scb, const void *buf, size_t count);
+extern void ser_base_write (struct serial *scb, const void *buf, size_t count);
 
 extern void ser_base_async (struct serial *scb, int async_p);
 extern int ser_base_readchar (struct serial *scb, int timeout);
index 30d908576dafd20d40d7866be92bc8d559799231..4607a10fde87564b49ee405946e6902e575b082c 100644 (file)
@@ -118,21 +118,21 @@ ser_windows_flush_input (struct serial *scb)
   return (PurgeComm (h, PURGE_RXCLEAR) != 0) ? 0 : -1;
 }
 
-static int
+static void
 ser_windows_send_break (struct serial *scb)
 {
   HANDLE h = (HANDLE) _get_osfhandle (scb->fd);
 
   if (SetCommBreak (h) == 0)
-    return -1;
+    throw_winerror_with_name ("error calling SetCommBreak",
+                             GetLastError ());
 
   /* Delay for 250 milliseconds.  */
   Sleep (250);
 
   if (ClearCommBreak (h) == 0)
-    return -1;
-
-  return 0;
+    throw_winerror_with_name ("error calling ClearCommBreak",
+                             GetLastError ());
 }
 
 static void
@@ -354,7 +354,7 @@ ser_windows_write_prim (struct serial *scb, const void *buf, size_t len)
     {
       if (GetLastError () != ERROR_IO_PENDING
          || !GetOverlappedResult (h, &ov, &bytes_written, TRUE))
-       bytes_written = -1;
+       throw_winerror_with_name ("error while writing", GetLastError ());
     }
 
   CloseHandle (ov.hEvent);
@@ -986,14 +986,14 @@ pipe_windows_write (struct serial *scb, const void *buf, size_t count)
 
   int pipeline_in_fd = fileno (ps->input);
   if (pipeline_in_fd < 0)
-    return -1;
+    error (_("could not find file number for pipe"));
 
   pipeline_in = (HANDLE) _get_osfhandle (pipeline_in_fd);
   if (pipeline_in == INVALID_HANDLE_VALUE)
-    return -1;
+    error (_("could not find handle for pipe"));
 
   if (! WriteFile (pipeline_in, buf, count, &written, NULL))
-    return -1;
+    throw_winerror_with_name (_("could not write to pipe"), GetLastError ());
 
   return written;
 }
index 5e36840082e100556cacab2e3eb852f992e93247..ce3c61815d8800c861eaddf1723724a878c6a0cb 100644 (file)
@@ -419,14 +419,17 @@ net_write_prim (struct serial *scb, const void *buf, size_t count)
      UNIX systems it is generally "const void *".  The cast to "const
      char *" is OK everywhere, since in C++ any data pointer type can
      be implicitly converted to "const void *".  */
-  return send (scb->fd, (const char *) buf, count, 0);
+  int result = send (scb->fd, (const char *) buf, count, 0);
+  if (result == -1 && errno != EINTR)
+    perror_with_name ("error while writing");
+  return result;
 }
 
-int
+void
 ser_tcp_send_break (struct serial *scb)
 {
   /* Send telnet IAC and BREAK characters.  */
-  return (serial_write (scb, "\377\363", 2));
+  serial_write (scb, "\377\363", 2);
 }
 
 #ifndef USE_WIN32API
index 444d77c0b74244f36900386dd7736afb078e773b..c22fd878d6d02d5538ee445bb047fbad3b442578 100644 (file)
@@ -26,6 +26,6 @@ extern void net_open (struct serial *scb, const char *name);
 extern void net_close (struct serial *scb);
 extern int net_read_prim (struct serial *scb, size_t count);
 extern int net_write_prim (struct serial *scb, const void *buf, size_t count);
-extern int ser_tcp_send_break (struct serial *scb);
+extern void ser_tcp_send_break (struct serial *scb);
 
 #endif
index e51058b534c5a7b49afcd670a4d40d9d23cd1c38..baa660be21d161c1e5c7fa56ac07cbfd706e6951 100644 (file)
@@ -75,7 +75,10 @@ uds_read_prim (struct serial *scb, size_t count)
 static int
 uds_write_prim (struct serial *scb, const void *buf, size_t count)
 {
-  return send (scb->fd, buf, count, 0);
+  int result = send (scb->fd, buf, count, 0);
+  if (result == -1 && errno != EINTR)
+    perror_with_name ("error while writing");
+  return result;
 }
 
 /* The local socket ops.  */
index 020b41e563db9cabaf7db9fb6a394821ebae34bb..a2a897d4442d8de1658c74d7691499702aac8ad6 100644 (file)
@@ -66,7 +66,7 @@ static void hardwire_print_tty_state (struct serial *, serial_ttystate,
 static int hardwire_drain_output (struct serial *);
 static int hardwire_flush_output (struct serial *);
 static int hardwire_flush_input (struct serial *);
-static int hardwire_send_break (struct serial *);
+static void hardwire_send_break (struct serial *);
 static int hardwire_setstopbits (struct serial *, int);
 
 /* Open up a real live device for serial I/O.  */
@@ -182,10 +182,11 @@ hardwire_flush_input (struct serial *scb)
   return tcflush (scb->fd, TCIFLUSH);
 }
 
-static int
+static void
 hardwire_send_break (struct serial *scb)
 {
-  return tcsendbreak (scb->fd, 0);
+  if (tcsendbreak (scb->fd, 0) == -1)
+    perror_with_name ("sending break");
 }
 
 static void
@@ -579,5 +580,8 @@ ser_unix_read_prim (struct serial *scb, size_t count)
 int
 ser_unix_write_prim (struct serial *scb, const void *buf, size_t len)
 {
-  return write (scb->fd, buf, len);
+  int result = write (scb->fd, buf, len);
+  if (result == -1 && errno != EINTR)
+    perror_with_name ("error while writing");
+  return result;
 }
index 720af1a356d4db63848dcb02e21393b21f9f3ad2..e8ad339aad88fbde9ac0d7325b0d1c866966f431 100644 (file)
@@ -399,7 +399,7 @@ serial_readchar (struct serial *scb, int timeout)
   return (ch);
 }
 
-int
+void
 serial_write (struct serial *scb, const void *buf, size_t count)
 {
   if (serial_logfp != NULL)
@@ -428,7 +428,7 @@ serial_write (struct serial *scb, const void *buf, size_t count)
       gdb_flush (gdb_stdlog);
     }
 
-  return (scb->ops->write (scb, buf, count));
+  scb->ops->write (scb, buf, count);
 }
 
 void
@@ -461,13 +461,13 @@ serial_flush_input (struct serial *scb)
   return scb->ops->flush_input (scb);
 }
 
-int
+void
 serial_send_break (struct serial *scb)
 {
   if (serial_logfp != NULL)
     serial_logchar (serial_logfp, 'w', SERIAL_BREAK, 0);
 
-  return (scb->ops->send_break (scb));
+  scb->ops->send_break (scb);
 }
 
 void
index 9ae7f4f13f1ceb530b3f0faf009df531f8437a93..50726bee2be164e31b35683cacc66adc209b680a 100644 (file)
@@ -119,10 +119,10 @@ enum serial_rc {
 
 extern int serial_readchar (struct serial *scb, int timeout);
 
-/* Write COUNT bytes from BUF to the port SCB.  Returns 0 for
-   success, non-zero for failure.  */
+/* Write COUNT bytes from BUF to the port SCB.  Throws exception on
+   error.  */
 
-extern int serial_write (struct serial *scb, const void *buf, size_t count);
+extern void serial_write (struct serial *scb, const void *buf, size_t count);
 
 /* Write a printf style string onto the serial port.  */
 
@@ -145,7 +145,7 @@ extern int serial_flush_input (struct serial *);
 
 /* Send a break between 0.25 and 0.5 seconds long.  */
 
-extern int serial_send_break (struct serial *scb);
+extern void serial_send_break (struct serial *scb);
 
 /* Turn the port into raw mode.  */
 
@@ -263,12 +263,12 @@ struct serial_ops
     void (*close) (struct serial *);
     int (*fdopen) (struct serial *, int fd);
     int (*readchar) (struct serial *, int timeout);
-    int (*write) (struct serial *, const void *buf, size_t count);
+    void (*write) (struct serial *, const void *buf, size_t count);
     /* Discard pending output */
     int (*flush_output) (struct serial *);
     /* Discard pending input */
     int (*flush_input) (struct serial *);
-    int (*send_break) (struct serial *);
+    void (*send_break) (struct serial *);
     void (*go_raw) (struct serial *);
     serial_ttystate (*get_tty_state) (struct serial *);
     serial_ttystate (*copy_tty_state) (struct serial *, serial_ttystate);