diff options
author | Tom Tromey <tromey@adacore.com> | 2023-09-06 08:33:46 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2023-11-27 12:55:14 -0700 |
commit | d69939bded50d76179f97284df35879a385cf8c0 (patch) | |
tree | 965bb45900e7a4442d3ce67e551d5cafe73e8691 | |
parent | a2e0acea420cca881296c6fcf58920f3d7c05a45 (diff) | |
download | fsf-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.c | 40 | ||||
-rw-r--r-- | gdb/ser-base.c | 8 | ||||
-rw-r--r-- | gdb/ser-base.h | 4 | ||||
-rw-r--r-- | gdb/ser-mingw.c | 18 | ||||
-rw-r--r-- | gdb/ser-tcp.c | 9 | ||||
-rw-r--r-- | gdb/ser-tcp.h | 2 | ||||
-rw-r--r-- | gdb/ser-uds.c | 5 | ||||
-rw-r--r-- | gdb/ser-unix.c | 12 | ||||
-rw-r--r-- | gdb/serial.c | 8 | ||||
-rw-r--r-- | gdb/serial.h | 12 |
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); |