aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Tromey <tromey@adacore.com>2023-09-06 08:33:46 -0600
committerTom Tromey <tromey@adacore.com>2023-11-27 12:55:14 -0700
commitd69939bded50d76179f97284df35879a385cf8c0 (patch)
tree965bb45900e7a4442d3ce67e551d5cafe73e8691
parenta2e0acea420cca881296c6fcf58920f3d7c05a45 (diff)
downloadfsf-binutils-gdb-d69939bded50d76179f97284df35879a385cf8c0.zip
fsf-binutils-gdb-d69939bded50d76179f97284df35879a385cf8c0.tar.gz
fsf-binutils-gdb-d69939bded50d76179f97284df35879a385cf8c0.tar.bz2
Change serial_send_break and serial_write to throw
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
-rw-r--r--gdb/remote.c40
-rw-r--r--gdb/ser-base.c8
-rw-r--r--gdb/ser-base.h4
-rw-r--r--gdb/ser-mingw.c18
-rw-r--r--gdb/ser-tcp.c9
-rw-r--r--gdb/ser-tcp.h2
-rw-r--r--gdb/ser-uds.c5
-rw-r--r--gdb/ser-unix.c12
-rw-r--r--gdb/serial.c8
-rw-r--r--gdb/serial.h12
10 files changed, 75 insertions, 43 deletions
diff --git a/gdb/remote.c b/gdb/remote.c
index 03ebcc6..49c1c96 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -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. */
diff --git a/gdb/ser-base.c b/gdb/ser-base.c
index 072211d..d83003e 100644
--- a/gdb/ser-base.c
+++ b/gdb/ser-base.c
@@ -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
diff --git a/gdb/ser-base.h b/gdb/ser-base.h
index aeb7a4d..539ea06 100644
--- a/gdb/ser-base.h
+++ b/gdb/ser-base.h
@@ -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);
diff --git a/gdb/ser-mingw.c b/gdb/ser-mingw.c
index 30d9085..4607a10 100644
--- a/gdb/ser-mingw.c
+++ b/gdb/ser-mingw.c
@@ -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;
}
diff --git a/gdb/ser-tcp.c b/gdb/ser-tcp.c
index 5e36840..ce3c618 100644
--- a/gdb/ser-tcp.c
+++ b/gdb/ser-tcp.c
@@ -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
diff --git a/gdb/ser-tcp.h b/gdb/ser-tcp.h
index 444d77c..c22fd87 100644
--- a/gdb/ser-tcp.h
+++ b/gdb/ser-tcp.h
@@ -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
diff --git a/gdb/ser-uds.c b/gdb/ser-uds.c
index e51058b..baa660b 100644
--- a/gdb/ser-uds.c
+++ b/gdb/ser-uds.c
@@ -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. */
diff --git a/gdb/ser-unix.c b/gdb/ser-unix.c
index 020b41e..a2a897d 100644
--- a/gdb/ser-unix.c
+++ b/gdb/ser-unix.c
@@ -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;
}
diff --git a/gdb/serial.c b/gdb/serial.c
index 720af1a..e8ad339 100644
--- a/gdb/serial.c
+++ b/gdb/serial.c
@@ -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
diff --git a/gdb/serial.h b/gdb/serial.h
index 9ae7f4f..50726be 100644
--- a/gdb/serial.h
+++ b/gdb/serial.h
@@ -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);