From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-oo1-xc2d.google.com (mail-oo1-xc2d.google.com [IPv6:2607:f8b0:4864:20::c2d]) by sourceware.org (Postfix) with ESMTPS id 5AACC3858291 for ; Tue, 12 Sep 2023 16:27:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5AACC3858291 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com Received: by mail-oo1-xc2d.google.com with SMTP id 006d021491bc7-5733789a44cso3449181eaf.2 for ; Tue, 12 Sep 2023 09:27:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adacore.com; s=google; t=1694536073; x=1695140873; darn=sourceware.org; h=to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=C05FpyXevCNRLe79TkLMxrcfWHIiZ6c7lskLFoSlZEw=; b=CpFBm6ML77BQUJfkEcoDPDlFtcSYO2JC84ouJy4RQ96dx25UyxbnrpxWX/RVVCOJqj 47RNtZ+X59amaq7+yVl/XSDi1rrlnbM5/UOtr99oxgyzQLMpYaBxxQ5lUYWjMtigp6xe PNGydYOREvWQzHaAvqGM9uvZlah1wGzqr90iM+lDSiuLgQKRsumcism+YtgSN5jyxFkN n/QJVlOnowo0BZIOa7FNguLdJwoJQuQwmUyavUKmiQ3VlaBMmkK8+q6u+KysTAfV4oO8 /JM0u7ziewm/qhFXuURYzXUP/R5iiHlTAyeS4fMw7njYkkHhEMtczxrArdfxn3ga6wau bSEw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1694536073; x=1695140873; h=to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=C05FpyXevCNRLe79TkLMxrcfWHIiZ6c7lskLFoSlZEw=; b=lnV6ttTV0AtwnG1ZZCbeR0WquUT31/9ZT0Z4cMeOcKgfkx8apyWvxKkMHbutGEQLjF VbSGZ2MGw4DtAW7CcD70/Ir2KfJaFJxHXBB464Sx2jM0nE7W9PaJEYkBnAjgMhZSMWch paqGdueL6iwgww8QidIuOD+L+ivnCUO3/aTbef/9aJkHIv9fpuFINYYd60nHFt6L1ik0 6G3dfr6dIMN60TZr3qS36QHI/G23d/homiYIXbZscnxZcF2fa412NMcO8XQYgwF7qk9W 15HGqt+aiDpW/4Wi9tnN0QOXRNWKqGw7qkQmqmQNc4fa2o3Pj3N/vZQ/XruKKOIdEJ+w jCeQ== X-Gm-Message-State: AOJu0YyftzYsU2xXMS5n0mhm8Pjm+W2LgyqVXeRl1PcR0e1bdclb4EWs aZYjPGh/PcrwNmpt0QuWvTU+ODf9MJNE1WktR06ZzQ== X-Google-Smtp-Source: AGHT+IEtGX61rDyyipTSBGGO4A+kDFMhAmLEZBcKGJg0hVWbpZSRbcwacdk+vdIXrjDpv+AOdOaqbA== X-Received: by 2002:a05:6870:c69a:b0:1d5:5a83:22b7 with SMTP id cv26-20020a056870c69a00b001d55a8322b7mr16981508oab.51.1694536073597; Tue, 12 Sep 2023 09:27:53 -0700 (PDT) Received: from localhost.localdomain (71-211-130-31.hlrn.qwest.net. [71.211.130.31]) by smtp.gmail.com with ESMTPSA id l1-20020a02cd81000000b0042b91ec7e31sm2872324jap.3.2023.09.12.09.27.52 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Sep 2023 09:27:53 -0700 (PDT) From: Tom Tromey Date: Tue, 12 Sep 2023 10:27:52 -0600 Subject: [PATCH 5/6] Change serial_send_break and serial_write to throw MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20230912-serial-exceptions-v1-5-af5097485390@adacore.com> References: <20230912-serial-exceptions-v1-0-af5097485390@adacore.com> In-Reply-To: <20230912-serial-exceptions-v1-0-af5097485390@adacore.com> To: gdb-patches@sourceware.org X-Mailer: b4 0.12.3 X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: 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 | 40 ++++++++++++++++++++++++++++++++-------- gdb/ser-base.c | 8 +++----- gdb/ser-base.h | 4 ++-- gdb/ser-mingw.c | 18 +++++++++--------- gdb/ser-tcp.c | 9 ++++++--- gdb/ser-tcp.h | 2 +- gdb/ser-uds.c | 5 ++++- gdb/ser-unix.c | 12 ++++++++---- gdb/serial.c | 8 ++++---- gdb/serial.h | 12 ++++++------ 10 files changed, 75 insertions(+), 43 deletions(-) diff --git a/gdb/remote.c b/gdb/remote.c index 646f869ef3a..23046beeb2e 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -1202,6 +1202,7 @@ class remote_target : public process_stratum_target 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); @@ -4553,15 +4554,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 @@ -4569,7 +4568,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. */ @@ -9672,16 +9670,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 072211df1ca..d83003ebf96 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 60f84e1f42e..6fcdf724413 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 30d908576da..4607a10fde8 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 75ea4c80051..62f8a519782 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 444d77c0b74..c22fd878d6d 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 e51058b534c..baa660be21d 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 020b41e563d..a2a897d4442 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 720af1a356d..e8ad339aad8 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 9ae7f4f13f1..50726bee2be 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); -- 2.40.1