From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24062 invoked by alias); 4 May 2019 06:24:37 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 24005 invoked by uid 89); 4 May 2019 06:24:24 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-9.1 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.1 spammy=launched X-HELO: mailsec118.isp.belgacom.be Received: from mailsec118.isp.belgacom.be (HELO mailsec118.isp.belgacom.be) (195.238.20.114) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 04 May 2019 06:24:14 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=skynet.be; i=@skynet.be; q=dns/txt; s=securemail; t=1556951054; x=1588487054; h=message-id:subject:from:to:date:in-reply-to:references: mime-version:content-transfer-encoding; bh=S2W64OXRM2hfxL9LWLJeH0zxQWtYp74w2zi7aEsiLwc=; b=sckuF1Xn/V3K9486pdFyIbn4KQDa3sHYN+4UhbawcDACFI1DIpq1rMkW gbQseqmWl0WYyVWt16jPe+4Ai79dFg==; Received: from 59.151-129-109.adsl-dyn.isp.belgacom.be (HELO md) ([109.129.151.59]) by relay.skynet.be with ESMTP/TLS/AES256-GCM-SHA384; 04 May 2019 08:24:11 +0200 Message-ID: <1556951051.1511.14.camel@skynet.be> Subject: Re: [RFAv2 4/6] Implement | (pipe) command. From: Philippe Waroquiers To: Pedro Alves , gdb-patches@sourceware.org Date: Sat, 04 May 2019 06:24:00 -0000 In-Reply-To: References: <20190426201108.7489-1-philippe.waroquiers@skynet.be> <20190426201108.7489-5-philippe.waroquiers@skynet.be> Content-Type: text/plain; charset="UTF-8" Mime-Version: 1.0 Content-Transfer-Encoding: 8bit X-IsSubscribed: yes X-SW-Source: 2019-05/txt/msg00123.txt.bz2 On Fri, 2019-05-03 at 19:59 +0100, Pedro Alves wrote: > On 4/26/19 9:11 PM, Philippe Waroquiers wrote: > > The pipe command allows to run a GDB command, and pipe its output > > to a shell command: > > (gdb) help pipe > > Send the output of a gdb command to a shell command. > > Usage: pipe [COMMAND] | SHELL_COMMAND > > Usage: | [COMMAND] | SHELL_COMMAND > > Usage: pipe -dX COMMAND X SHELL_COMMAND > > Usage: | -dX COMMAND X SHELL_COMMAND > > Executes COMMAND and sends its output to SHELL_COMMAND. > > If COMMAND contains a | character, the option -dX indicates > > to use the character X to separate COMMAND from SHELL_COMMAND. > > With no COMMAND, repeat the last executed command > > and send its output to SHELL_COMMAND. > > (gdb) > > I think that making "-dX" a single character is a mistake. I'd rather > make that "-d STRING", so you can use use a string that is much less > likely to conflict. Like bash herestrings. So a user would be able > to do: > > pipe -d XXXYYYXXX $command | $shell_command > > I also think "-dX" without a space in between is very non-gdb-ish. > In gdb, you kind of either have "-OPT X", or "/OX", which is kind of > double "--" vs "-" with getopt, except with different leading > tokens. Ok, will change to -d STRING. > > > > > For example: > > (gdb) pipe print some_data_structure | grep -B3 -A3 something > > > > The pipe character is defined as an alias for pipe command, so that > > the above can be typed as: > > (gdb) | print some_data_structure | grep -B3 -A3 something > > > > I get that "it makes sense", but do you see yourself using the "|" command > in preference to "pipe"? "pipe" can be typed as "pi", which is two > key strokes as well. Kind of wondering whether the character could be > saved for something else in the future. I don't have a use in mind, > just thinking out loud. Yes, I always use "|" (I even just checked the test to be sure that I also tested "pipe" and not only "|"). pip must be used, as pi launches an interactive python. Also, "|" allows to do: (gdb) some_command ... (gdb) ||grep something_in_some_command_output (gdb) ||tee save_some_command_output which is better than (gdb) pip|grep something_in_some_command_output > > > If no GDB COMMAND is given, then the previous command is relaunched, > > and its output is sent to the given SHELL_COMMAND. > > > > + command = skip_spaces (command); > > + std::string gdb_cmd (command, shell_command - command); > > + > > + if (gdb_cmd.empty ()) > > + { > > + repeat_previous (); > > + gdb_cmd = skip_spaces (get_saved_command_line ()); > > + if (gdb_cmd.empty ()) > > + error (_("No previous command to relaunch")); > > + } > > + > > + shell_command++; /* skip the separator. */ > > Uppercase "Skip". > > > + shell_command = skip_spaces (shell_command); > > + if (*shell_command == 0) > > if (*shell_command == '\0') > > > > + { > > + if (separator == '|') > > I don't think this check is 100% right, considering that you could do: That part of the code will change heavily when the separator becomes a string. > > (gdb) pipe -d| SHELL_COMMAND > > I.e., what you want to check is whether a separate was explicitly specified. > > > + error (_("Missing SHELL_COMMAND in \"| [COMMAND] | SHELL_COMMAND\"")); > > + else > > + error (_("Missing SHELL_COMMAND in " > > + "\"| -d%c COMMAND %c SHELL_COMMAND\""), > > + separator, separator); > > Or instead of making this dynamic, just print something like: > > error (_("Missing SHELL_COMMAND.\n" > "Usage: \"| [-c SEP] [COMMAND] | SHELL_COMMAND\"")); > > > > + } > > + > > + FILE *to_shell_command = popen (shell_command, "w"); > > + > > + if (to_shell_command == NULL) > > + error (_("Error launching \"%s\""), shell_command); > > + > > + try > > + { > > + stdio_file pipe_file (to_shell_command); > > + > > + execute_command_to_ui_file (&pipe_file, gdb_cmd.c_str (), from_tty); > > + } > > + catch (const gdb_exception_error &ex) > > + { > > + pclose (to_shell_command); > > + throw; > > + } > > + > > + int shell_command_status = pclose (to_shell_command); > > + > > + if (shell_command_status < 0) > > + error (_("shell command \"%s\" errno %s"), shell_command, > > + safe_strerror (errno)); > > + if (shell_command_status > 0) > > + { > > + if (WIFEXITED (shell_command_status)) > > + warning (_("shell command \"%s\" exit status %d"), shell_command, > > + WEXITSTATUS (shell_command_status)); > > + else if (WIFSIGNALED (shell_command_status)) > > + warning (_("shell command \"%s\" exit with signal %d"), shell_command, > > + WTERMSIG (shell_command_status)); > > + else > > + warning (_("shell command \"%s\" status %d"), shell_command, > > + shell_command_status); > > + } > > Is there a reason this isn't using the pex routines? pex routines do not help to handle the exit status (and are also not used for "shell"). However your question now makes me believe that it is not a good idea to systematically report to the user the exit status of the launched command. E.g. in a shell, if you do: $ echo something | grep somethingelse the shell does not tell you: warning: grep has exited with status 1 which is what the GDB patch does now ! I think it is up to each command to have its way to  report success or failure. So, I believe the correct solution is to have a convenience variable (e.g. $_exit_status) set with the exit status of the last launched command (either by the GDB shell or pipe command). This convenience variable can then be looked at by the user if there is a doubt about how the last command worked. And more interesting, this convenience variable can be used in user defined commands. I will prepare a RFAv3 based on this. Thanks for the review Philippe