[lldb] Have Host::RunShellCommand ret stderr & stdout seperately (#184548)
Host::RunShellCommand takes a std::string *command_output argument and a bool hide_stderr=false defaulted argument. If the shell command returns stderr and stdout text, it is intermixed in the same command_output, unless hide_stderr=true. In SymbolLocatorDebugSymbols::DownloadObjectAndSymbolFile we call an external program to find a binary and dSYM by uuid, and the external program returns a plist (xml) output. In some cases, it printed a (harmless) warning message to stderr, and then a complete plist output to stdout. We attempt to parse the combination of these two streams, and the parse fails - we don't get the output. This patch removes hide_stderr and instead adds a `std::string *separated_error_output` argument. If `separated_error_output` is nullptr, output and error texts are returned combined in the `command_output` argument. If a std::string object address is provided for `separated_error_output`, then standard error output is separated into this string. A caller which wants the old `hide_stderr=true` behavior should pass a throwaway std::string object to `RunShellCommand` and ignore it. rdar://168621579
This commit is contained in:
parent
3829fdb8af
commit
1c228a0533
@ -195,65 +195,117 @@ public:
|
||||
static Status ShellExpandArguments(ProcessLaunchInfo &launch_info);
|
||||
|
||||
/// Run a shell command.
|
||||
/// \arg command shouldn't be empty
|
||||
/// \arg working_dir Pass empty FileSpec to use the current working directory
|
||||
/// \arg status_ptr Pass NULL if you don't want the process exit status
|
||||
/// \arg signo_ptr Pass NULL if you don't want the signal that caused the
|
||||
/// process to exit
|
||||
/// \arg command_output Pass NULL if you don't want the command output
|
||||
/// \arg hide_stderr if this is false, redirect stderr to stdout
|
||||
/// \param[in] command
|
||||
/// Command to execute, should not be empty.
|
||||
/// \param[in] working_dir
|
||||
/// Pass empty FileSpec to use the current working directory
|
||||
/// \param[out] status_ptr
|
||||
/// Pass nullptr if you don't want the process exit status
|
||||
/// \param[out] signo_ptr
|
||||
/// Pass nullptr if you don't want the signal that caused the
|
||||
/// process to exit
|
||||
/// \param[out] command_output
|
||||
/// Pass nullptr if you don't want the command output
|
||||
/// \param[out] separated_error_output
|
||||
/// If a std::string is specified, error output is routed
|
||||
/// into a separate string. If nullptr is provided,
|
||||
/// command output and error text will be returned combined
|
||||
/// in \a command_output.
|
||||
/// \param[in] timeout
|
||||
/// Timeout duration to enforce
|
||||
/// \param[in] run_in_shell
|
||||
/// Run in a subshell, with glob expansion of args
|
||||
static Status RunShellCommand(llvm::StringRef command,
|
||||
const FileSpec &working_dir, int *status_ptr,
|
||||
int *signo_ptr, std::string *command_output,
|
||||
std::string *error_output,
|
||||
const Timeout<std::micro> &timeout,
|
||||
bool run_in_shell = true,
|
||||
bool hide_stderr = false);
|
||||
bool run_in_shell = true);
|
||||
|
||||
/// Run a shell command.
|
||||
/// \arg shell Pass an empty string if you want to use the default shell
|
||||
/// interpreter \arg command \arg working_dir Pass empty FileSpec to use the
|
||||
/// current working directory \arg status_ptr Pass NULL if you don't want
|
||||
/// the process exit status \arg signo_ptr Pass NULL if you don't want the
|
||||
/// signal that caused
|
||||
/// the process to exit
|
||||
/// \arg command_output Pass NULL if you don't want the command output
|
||||
/// \arg hide_stderr If this is \b false, redirect stderr to stdout
|
||||
/// \param[in] shell
|
||||
/// Pass an empty string to use the default shell
|
||||
/// \param[in] command
|
||||
/// Command to execute, should not be empty.
|
||||
/// \param[in] working_dir
|
||||
/// Pass empty FileSpec to use the current working directory
|
||||
/// \param[out] status_ptr
|
||||
/// Pass nullptr if you don't want the process exit status
|
||||
/// \param[out] signo_ptr
|
||||
/// Pass nullptr if you don't want the signal that caused the
|
||||
/// process to exit
|
||||
/// \param[out] command_output
|
||||
/// Pass nullptr if you don't want the command output
|
||||
/// \param[out] separated_error_output
|
||||
/// If a std::string is specified, error output is routed
|
||||
/// into a separate string. If nullptr is provided,
|
||||
/// command output and error text will be returned combined
|
||||
/// \param[in] timeout
|
||||
/// Timeout duration to enforce
|
||||
/// \param[in] run_in_shell
|
||||
/// Run in a subshell, with glob expansion of args
|
||||
static Status RunShellCommand(llvm::StringRef shell, llvm::StringRef command,
|
||||
const FileSpec &working_dir, int *status_ptr,
|
||||
int *signo_ptr, std::string *command_output,
|
||||
std::string *separated_error_output,
|
||||
const Timeout<std::micro> &timeout,
|
||||
bool run_in_shell = true,
|
||||
bool hide_stderr = false);
|
||||
bool run_in_shell = true);
|
||||
|
||||
/// Run a shell command.
|
||||
/// \arg working_dir Pass empty FileSpec to use the current working directory
|
||||
/// \arg status_ptr Pass NULL if you don't want the process exit status
|
||||
/// \arg signo_ptr Pass NULL if you don't want the signal that caused the
|
||||
/// process to exit
|
||||
/// \arg command_output Pass NULL if you don't want the command output
|
||||
/// \arg hide_stderr if this is false, redirect stderr to stdout
|
||||
/// \param[in] args
|
||||
/// Command to execute
|
||||
/// \param[in] working_dir
|
||||
/// Pass empty FileSpec to use the current working directory
|
||||
/// \param[out] status_ptr
|
||||
/// Pass nullptr if you don't want the process exit status
|
||||
/// \param[out] signo_ptr
|
||||
/// Pass nullptr if you don't want the signal that caused the
|
||||
/// process to exit
|
||||
/// \param[out] command_output
|
||||
/// Pass nullptr if you don't want the command output
|
||||
/// \param[out] separated_error_output
|
||||
/// If a std::string is specified, error output is routed
|
||||
/// into a separate string. If nullptr is provided,
|
||||
/// command output and error text will be returned combined
|
||||
/// \param[in] timeout
|
||||
/// Timeout duration to enforce
|
||||
/// \param[in] run_in_shell
|
||||
/// Run in a subshell, with glob expansion of args
|
||||
static Status RunShellCommand(const Args &args, const FileSpec &working_dir,
|
||||
int *status_ptr, int *signo_ptr,
|
||||
std::string *command_output,
|
||||
std::string *separated_error_output,
|
||||
const Timeout<std::micro> &timeout,
|
||||
bool run_in_shell = true,
|
||||
bool hide_stderr = false);
|
||||
bool run_in_shell = true);
|
||||
|
||||
/// Run a shell command.
|
||||
/// \arg shell Pass an empty string if you want to use the default
|
||||
/// shell interpreter \arg command \arg working_dir Pass empty FileSpec to use
|
||||
/// the current working directory \arg status_ptr Pass NULL if you don't
|
||||
/// want the process exit status \arg signo_ptr Pass NULL if you don't
|
||||
/// want the signal that caused the
|
||||
/// process to exit
|
||||
/// \arg command_output Pass NULL if you don't want the command output
|
||||
/// \arg hide_stderr If this is \b false, redirect stderr to stdout
|
||||
/// \param[in] shell
|
||||
/// Pass an empty string to use the default shell
|
||||
/// \param[in] args
|
||||
/// Command to execute
|
||||
/// \param[in] working_dir
|
||||
/// Pass empty FileSpec to use the current working directory
|
||||
/// \param[out] status_ptr
|
||||
/// Pass nullptr if you don't want the process exit status
|
||||
/// \param[out] signo_ptr
|
||||
/// Pass nullptr if you don't want the signal that caused the
|
||||
/// process to exit
|
||||
/// \param[out] command_output
|
||||
/// Pass nullptr if you don't want the command output
|
||||
/// \param[out] separated_error_output
|
||||
/// If a std::string is specified, error output is routed
|
||||
/// into a separate string. If nullptr is provided,
|
||||
/// command output and error text will be returned combined
|
||||
/// \param[in] timeout
|
||||
/// Timeout duration to enforce
|
||||
/// \param[in] run_in_shell
|
||||
/// Run in a subshell, with glob expansion of args
|
||||
static Status RunShellCommand(llvm::StringRef shell, const Args &args,
|
||||
const FileSpec &working_dir, int *status_ptr,
|
||||
int *signo_ptr, std::string *command_output,
|
||||
std::string *separated_error_output,
|
||||
const Timeout<std::micro> &timeout,
|
||||
bool run_in_shell = true,
|
||||
bool hide_stderr = false);
|
||||
bool run_in_shell = true);
|
||||
|
||||
static llvm::Error OpenFileInExternalEditor(llvm::StringRef editor,
|
||||
const FileSpec &file_spec,
|
||||
|
||||
@ -679,6 +679,9 @@ public:
|
||||
// the process to exit
|
||||
std::string
|
||||
*command_output, // Pass nullptr if you don't want the command output
|
||||
std::string
|
||||
*separated_error_output, // Pass nullptr to have error and command
|
||||
// output combined in command_output.
|
||||
const Timeout<std::micro> &timeout);
|
||||
|
||||
virtual lldb_private::Status RunShellCommand(
|
||||
@ -690,6 +693,9 @@ public:
|
||||
// the process to exit
|
||||
std::string
|
||||
*command_output, // Pass nullptr if you don't want the command output
|
||||
std::string
|
||||
*separated_error_output, // Pass nullptr to have error and command
|
||||
// output combined in command_output.
|
||||
const Timeout<std::micro> &timeout);
|
||||
|
||||
virtual void SetLocalCacheDirectory(const char *local);
|
||||
|
||||
@ -71,11 +71,13 @@ public:
|
||||
Status RunShellCommand(llvm::StringRef command, const FileSpec &working_dir,
|
||||
int *status_ptr, int *signo_ptr,
|
||||
std::string *command_output,
|
||||
std::string *separated_error_output,
|
||||
const Timeout<std::micro> &timeout) override;
|
||||
|
||||
Status RunShellCommand(llvm::StringRef interpreter, llvm::StringRef command,
|
||||
const FileSpec &working_dir, int *status_ptr,
|
||||
int *signo_ptr, std::string *command_output,
|
||||
std::string *separated_error_output,
|
||||
const Timeout<std::micro> &timeout) override;
|
||||
|
||||
const char *GetHostname() override;
|
||||
|
||||
@ -564,7 +564,7 @@ SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) {
|
||||
FileSpec(shell_command.GetWorkingDirectory()),
|
||||
&shell_command.m_opaque_ptr->m_status,
|
||||
&shell_command.m_opaque_ptr->m_signo,
|
||||
&shell_command.m_opaque_ptr->m_output,
|
||||
&shell_command.m_opaque_ptr->m_output, nullptr,
|
||||
shell_command.m_opaque_ptr->m_timeout);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1707,9 +1707,9 @@ public:
|
||||
std::string output;
|
||||
int status = -1;
|
||||
int signo = -1;
|
||||
error = (platform_sp->RunShellCommand(m_options.m_shell_interpreter, cmd,
|
||||
working_dir, &status, &signo,
|
||||
&output, m_options.m_timeout));
|
||||
error = (platform_sp->RunShellCommand(
|
||||
m_options.m_shell_interpreter, cmd, working_dir, &status, &signo,
|
||||
&output, nullptr, m_options.m_timeout));
|
||||
if (!output.empty())
|
||||
result.GetOutputStream().PutCString(output);
|
||||
if (status > 0) {
|
||||
|
||||
@ -389,39 +389,43 @@ MonitorShellCommand(std::shared_ptr<ShellInfo> shell_info, lldb::pid_t pid,
|
||||
Status Host::RunShellCommand(llvm::StringRef command,
|
||||
const FileSpec &working_dir, int *status_ptr,
|
||||
int *signo_ptr, std::string *command_output_ptr,
|
||||
std::string *separated_error_output,
|
||||
const Timeout<std::micro> &timeout,
|
||||
bool run_in_shell, bool hide_stderr) {
|
||||
bool run_in_shell) {
|
||||
return RunShellCommand(llvm::StringRef(), Args(command), working_dir,
|
||||
status_ptr, signo_ptr, command_output_ptr, timeout,
|
||||
run_in_shell, hide_stderr);
|
||||
status_ptr, signo_ptr, command_output_ptr,
|
||||
separated_error_output, timeout, run_in_shell);
|
||||
}
|
||||
|
||||
Status Host::RunShellCommand(llvm::StringRef shell_path,
|
||||
llvm::StringRef command,
|
||||
const FileSpec &working_dir, int *status_ptr,
|
||||
int *signo_ptr, std::string *command_output_ptr,
|
||||
std::string *separated_error_output,
|
||||
const Timeout<std::micro> &timeout,
|
||||
bool run_in_shell, bool hide_stderr) {
|
||||
bool run_in_shell) {
|
||||
return RunShellCommand(shell_path, Args(command), working_dir, status_ptr,
|
||||
signo_ptr, command_output_ptr, timeout, run_in_shell,
|
||||
hide_stderr);
|
||||
signo_ptr, command_output_ptr, separated_error_output,
|
||||
timeout, run_in_shell);
|
||||
}
|
||||
|
||||
Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir,
|
||||
int *status_ptr, int *signo_ptr,
|
||||
std::string *command_output_ptr,
|
||||
std::string *separated_error_output,
|
||||
const Timeout<std::micro> &timeout,
|
||||
bool run_in_shell, bool hide_stderr) {
|
||||
bool run_in_shell) {
|
||||
return RunShellCommand(llvm::StringRef(), args, working_dir, status_ptr,
|
||||
signo_ptr, command_output_ptr, timeout, run_in_shell,
|
||||
hide_stderr);
|
||||
signo_ptr, command_output_ptr, separated_error_output,
|
||||
timeout, run_in_shell);
|
||||
}
|
||||
|
||||
Status Host::RunShellCommand(llvm::StringRef shell_path, const Args &args,
|
||||
const FileSpec &working_dir, int *status_ptr,
|
||||
int *signo_ptr, std::string *command_output_ptr,
|
||||
std::string *separated_error_output,
|
||||
const Timeout<std::micro> &timeout,
|
||||
bool run_in_shell, bool hide_stderr) {
|
||||
bool run_in_shell) {
|
||||
Status error;
|
||||
ProcessLaunchInfo launch_info;
|
||||
launch_info.SetArchitecture(HostInfo::GetArchitecture());
|
||||
@ -448,9 +452,10 @@ Status Host::RunShellCommand(llvm::StringRef shell_path, const Args &args,
|
||||
if (working_dir)
|
||||
launch_info.SetWorkingDirectory(working_dir);
|
||||
llvm::SmallString<64> output_file_path;
|
||||
llvm::SmallString<64> error_file_path;
|
||||
|
||||
if (command_output_ptr) {
|
||||
// Create a temporary file to get the stdout/stderr and redirect the output
|
||||
// Create a temporary file to get the stdout and redirect the output
|
||||
// of the command into this file. We will later read this file if all goes
|
||||
// well and fill the data into "command_output_ptr"
|
||||
if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
|
||||
@ -463,7 +468,22 @@ Status Host::RunShellCommand(llvm::StringRef shell_path, const Args &args,
|
||||
}
|
||||
}
|
||||
|
||||
if (separated_error_output) {
|
||||
// Create a temporary file to get the stderr and redirect the output
|
||||
// of the command into this file. We will later read this file if all goes
|
||||
// well and fill the data into "separated_error_output".
|
||||
if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
|
||||
tmpdir_file_spec.AppendPathComponent("lldb-shell-error.%%%%%%");
|
||||
llvm::sys::fs::createUniqueFile(tmpdir_file_spec.GetPath(),
|
||||
error_file_path);
|
||||
} else {
|
||||
llvm::sys::fs::createTemporaryFile("lldb-shell-error.%%%%%%", "",
|
||||
error_file_path);
|
||||
}
|
||||
}
|
||||
|
||||
FileSpec output_file_spec(output_file_path.str());
|
||||
FileSpec error_file_spec(error_file_path.str());
|
||||
// Set up file descriptors.
|
||||
launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false);
|
||||
if (output_file_spec)
|
||||
@ -472,10 +492,11 @@ Status Host::RunShellCommand(llvm::StringRef shell_path, const Args &args,
|
||||
else
|
||||
launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true);
|
||||
|
||||
if (output_file_spec && !hide_stderr)
|
||||
launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO);
|
||||
if (error_file_spec)
|
||||
launch_info.AppendOpenFileAction(STDERR_FILENO, error_file_spec, false,
|
||||
true);
|
||||
else
|
||||
launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true);
|
||||
launch_info.AppendDuplicateFileAction(STDOUT_FILENO, STDERR_FILENO);
|
||||
|
||||
std::shared_ptr<ShellInfo> shell_info_sp(new ShellInfo());
|
||||
launch_info.SetMonitorProcessCallback(
|
||||
@ -524,10 +545,33 @@ Status Host::RunShellCommand(llvm::StringRef shell_path, const Args &args,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (separated_error_output) {
|
||||
separated_error_output->clear();
|
||||
uint64_t file_size =
|
||||
FileSystem::Instance().GetByteSize(error_file_spec);
|
||||
if (file_size > 0) {
|
||||
if (file_size > separated_error_output->max_size()) {
|
||||
error = Status::FromErrorStringWithFormat(
|
||||
"shell command error output is too large to fit into a "
|
||||
"std::string");
|
||||
} else {
|
||||
WritableDataBufferSP Buffer =
|
||||
FileSystem::Instance().CreateWritableDataBuffer(
|
||||
error_file_spec);
|
||||
if (error.Success())
|
||||
separated_error_output->assign(
|
||||
reinterpret_cast<char *>(Buffer->GetBytes()),
|
||||
Buffer->GetByteSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
llvm::sys::fs::remove(output_file_spec.GetPath());
|
||||
if (output_file_spec)
|
||||
llvm::sys::fs::remove(output_file_spec.GetPath());
|
||||
if (error_file_spec)
|
||||
llvm::sys::fs::remove(error_file_spec.GetPath());
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@ -1530,10 +1530,11 @@ Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
|
||||
}
|
||||
}
|
||||
bool run_in_shell = true;
|
||||
bool hide_stderr = true;
|
||||
std::string error_output; // Pass stderr string arg so it is not mixed with
|
||||
// stdout.
|
||||
Status e =
|
||||
RunShellCommand(expand_command, cwd, &status, nullptr, &output,
|
||||
std::chrono::seconds(10), run_in_shell, hide_stderr);
|
||||
&error_output, std::chrono::seconds(10), run_in_shell);
|
||||
|
||||
if (e.Fail())
|
||||
return e;
|
||||
|
||||
@ -456,8 +456,9 @@ xcrun(const std::string &sdk, llvm::ArrayRef<llvm::StringRef> arguments,
|
||||
// xcrun can take surprisingly long to build up its database.
|
||||
auto timeout = std::chrono::seconds(60);
|
||||
bool run_in_shell = false;
|
||||
lldb_private::Status error = Host::RunShellCommand(
|
||||
args, FileSpec(), &status, &signo, &output_str, timeout, run_in_shell);
|
||||
lldb_private::Status error =
|
||||
Host::RunShellCommand(args, FileSpec(), &status, &signo, &output_str,
|
||||
nullptr, timeout, run_in_shell);
|
||||
|
||||
// Check that xcrun returned something useful.
|
||||
if (error.Fail()) {
|
||||
|
||||
@ -231,9 +231,9 @@ Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
|
||||
int status;
|
||||
std::string output;
|
||||
std::string command = expand_command.GetString().str();
|
||||
Status e =
|
||||
RunShellCommand(command.c_str(), launch_info.GetWorkingDirectory(),
|
||||
&status, nullptr, &output, std::chrono::seconds(10));
|
||||
Status e = RunShellCommand(
|
||||
command.c_str(), launch_info.GetWorkingDirectory(), &status, nullptr,
|
||||
&output, nullptr, std::chrono::seconds(10));
|
||||
|
||||
if (e.Fail())
|
||||
return e;
|
||||
|
||||
@ -683,7 +683,7 @@ static FileSpec GetXcodeSelectPath() {
|
||||
Status status =
|
||||
Host::RunShellCommand("/usr/bin/xcode-select --print-path",
|
||||
FileSpec(), // current working directory
|
||||
&exit_status, &signo, &command_output,
|
||||
&exit_status, &signo, &command_output, nullptr,
|
||||
std::chrono::seconds(2), // short timeout
|
||||
false); // don't run in a shell
|
||||
if (status.Success() && exit_status == 0 && !command_output.empty()) {
|
||||
|
||||
@ -84,7 +84,7 @@ static uint32_t chown_file(Platform *platform, const char *path,
|
||||
command.Printf("%s", path);
|
||||
int status;
|
||||
platform->RunShellCommand(command.GetData(), FileSpec(), &status, nullptr,
|
||||
nullptr, std::chrono::seconds(10));
|
||||
nullptr, nullptr, std::chrono::seconds(10));
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
|
||||
command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
|
||||
int status;
|
||||
RunShellCommand(command.GetData(), FileSpec(), &status, nullptr, nullptr,
|
||||
std::chrono::seconds(10));
|
||||
nullptr, std::chrono::seconds(10));
|
||||
if (status != 0)
|
||||
return Status::FromErrorString("unable to perform copy");
|
||||
if (uid == UINT32_MAX && gid == UINT32_MAX)
|
||||
@ -140,7 +140,7 @@ PlatformPOSIX::PutFile(const lldb_private::FileSpec &source,
|
||||
LLDB_LOGF(log, "[PutFile] Running command: %s\n", command.GetData());
|
||||
int retcode;
|
||||
Host::RunShellCommand(command.GetData(), FileSpec(), &retcode, nullptr,
|
||||
nullptr, std::chrono::minutes(1));
|
||||
nullptr, nullptr, std::chrono::minutes(1));
|
||||
if (retcode == 0) {
|
||||
// Don't chown a local file for a remote system
|
||||
// if (chown_file(this,dst_path.c_str(),uid,gid) != 0)
|
||||
@ -178,7 +178,7 @@ lldb_private::Status PlatformPOSIX::GetFile(
|
||||
cp_command.Printf("cp %s %s", src_path.c_str(), dst_path.c_str());
|
||||
int status;
|
||||
RunShellCommand(cp_command.GetData(), FileSpec(), &status, nullptr, nullptr,
|
||||
std::chrono::seconds(10));
|
||||
nullptr, std::chrono::seconds(10));
|
||||
if (status != 0)
|
||||
return Status::FromErrorString("unable to perform copy");
|
||||
return Status();
|
||||
@ -199,7 +199,7 @@ lldb_private::Status PlatformPOSIX::GetFile(
|
||||
LLDB_LOGF(log, "[GetFile] Running command: %s\n", command.GetData());
|
||||
int retcode;
|
||||
Host::RunShellCommand(command.GetData(), FileSpec(), &retcode, nullptr,
|
||||
nullptr, std::chrono::minutes(1));
|
||||
nullptr, nullptr, std::chrono::minutes(1));
|
||||
if (retcode == 0)
|
||||
return Status();
|
||||
// If we are here, rsync has failed - let's try the slow way before
|
||||
|
||||
@ -684,12 +684,15 @@ Status PlatformRemoteGDBServer::RunShellCommand(
|
||||
int *signo_ptr, // Pass NULL if you don't want the signal that caused the
|
||||
// process to exit
|
||||
std::string
|
||||
*command_output, // Pass NULL if you don't want the command output
|
||||
*command_output, // Pass nullptr if you don't want the command output
|
||||
std::string *separated_error_output, // Pass nullptr if you don't want the
|
||||
// error output
|
||||
const Timeout<std::micro> &timeout) {
|
||||
if (!IsConnected())
|
||||
return Status::FromErrorStringWithFormat("Not connected.");
|
||||
return m_gdb_client_up->RunShellCommand(command, working_dir, status_ptr,
|
||||
signo_ptr, command_output, timeout);
|
||||
signo_ptr, command_output,
|
||||
separated_error_output, timeout);
|
||||
}
|
||||
|
||||
llvm::ErrorOr<llvm::MD5::MD5Result>
|
||||
|
||||
@ -141,7 +141,10 @@ public:
|
||||
int *signo_ptr, // Pass NULL if you don't want the signal that caused the
|
||||
// process to exit
|
||||
std::string
|
||||
*command_output, // Pass NULL if you don't want the command output
|
||||
*command_output, // Pass nullptr if you don't want the command output
|
||||
std::string
|
||||
*separated_error_outputerror_output, // Pass nullptr if you don't want
|
||||
// the command error output
|
||||
const lldb_private::Timeout<std::micro> &timeout) override;
|
||||
|
||||
void CalculateTrapHandlerSymbolNames() override;
|
||||
|
||||
@ -2983,7 +2983,9 @@ lldb_private::Status GDBRemoteCommunicationClient::RunShellCommand(
|
||||
int *signo_ptr, // Pass NULL if you don't want the signal that caused the
|
||||
// process to exit
|
||||
std::string
|
||||
*command_output, // Pass NULL if you don't want the command output
|
||||
*command_output, // Pass nullptr if you don't want the command output
|
||||
std::string *separated_error_output, // Pass nullptr if you don't want the
|
||||
// command error output
|
||||
const Timeout<std::micro> &timeout) {
|
||||
lldb_private::StreamString stream;
|
||||
stream.PutCString("qPlatform_shell:");
|
||||
|
||||
@ -403,6 +403,8 @@ public:
|
||||
// the process to exit
|
||||
std::string
|
||||
*command_output, // Pass nullptr if you don't want the command output
|
||||
std::string *separated_error_output, // Pass nullptr if you don't want the
|
||||
// command error output
|
||||
const Timeout<std::micro> &timeout);
|
||||
|
||||
llvm::ErrorOr<llvm::MD5::MD5Result> CalculateMD5(const FileSpec &file_spec);
|
||||
|
||||
@ -752,7 +752,7 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell(
|
||||
FileSystem::Instance().Resolve(working_spec);
|
||||
Status err =
|
||||
Host::RunShellCommand(path.c_str(), working_spec, &status, &signo,
|
||||
&output, std::chrono::seconds(10));
|
||||
&output, nullptr, std::chrono::seconds(10));
|
||||
StreamGDBRemote response;
|
||||
if (err.Fail()) {
|
||||
response.PutCString("F,");
|
||||
|
||||
@ -1095,20 +1095,24 @@ bool SymbolLocatorDebugSymbols::DownloadObjectAndSymbolFile(
|
||||
int exit_status = -1;
|
||||
int signo = -1;
|
||||
std::string command_output;
|
||||
std::string error_output;
|
||||
error = Host::RunShellCommand(
|
||||
command.GetData(),
|
||||
FileSpec(), // current working directory
|
||||
&exit_status, // Exit status
|
||||
&signo, // Signal int *
|
||||
&command_output, // Command output
|
||||
&error_output, // Command error output
|
||||
std::chrono::seconds(
|
||||
640), // Large timeout to allow for long dsym download times
|
||||
false); // Don't run in a shell (we don't need shell expansion)
|
||||
|
||||
if (error.Fail() || exit_status != 0 || command_output.empty()) {
|
||||
LLDB_LOGF(log, "'%s' failed (exit status: %d, error: '%s', output: '%s')",
|
||||
LLDB_LOGF(log,
|
||||
"'%s' failed (exit status: %d, error: '%s', stdout: '%s', "
|
||||
"stderr: '%s')",
|
||||
command.GetData(), exit_status, error.AsCString(),
|
||||
command_output.c_str());
|
||||
command_output.c_str(), error_output.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1123,6 +1127,7 @@ bool SymbolLocatorDebugSymbols::DownloadObjectAndSymbolFile(
|
||||
if (!plist.get()) {
|
||||
LLDB_LOGF(log, "'%s' failed: output is not a valid plist",
|
||||
command.GetData());
|
||||
LLDB_LOGF(log, "Response:\n%s\n", command_output.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -1241,9 +1241,12 @@ lldb_private::Status Platform::RunShellCommand(
|
||||
// process to exit
|
||||
std::string
|
||||
*command_output, // Pass nullptr if you don't want the command output
|
||||
std::string *separated_error_output, // Pass nullptr if you don't want the
|
||||
// command error output
|
||||
const Timeout<std::micro> &timeout) {
|
||||
return RunShellCommand(llvm::StringRef(), command, working_dir, status_ptr,
|
||||
signo_ptr, command_output, timeout);
|
||||
signo_ptr, command_output, separated_error_output,
|
||||
timeout);
|
||||
}
|
||||
|
||||
lldb_private::Status Platform::RunShellCommand(
|
||||
@ -1257,10 +1260,13 @@ lldb_private::Status Platform::RunShellCommand(
|
||||
// process to exit
|
||||
std::string
|
||||
*command_output, // Pass nullptr if you don't want the command output
|
||||
std::string *separated_error_output, // Pass nullptr if you don't want the
|
||||
// command error output
|
||||
const Timeout<std::micro> &timeout) {
|
||||
if (IsHost())
|
||||
return Host::RunShellCommand(shell, command, working_dir, status_ptr,
|
||||
signo_ptr, command_output, timeout);
|
||||
signo_ptr, command_output,
|
||||
separated_error_output, timeout);
|
||||
return Status::FromErrorString(
|
||||
"unable to run a remote command without a platform");
|
||||
}
|
||||
|
||||
@ -55,21 +55,23 @@ Status RemoteAwarePlatform::ResolveExecutable(const ModuleSpec &module_spec,
|
||||
Status RemoteAwarePlatform::RunShellCommand(
|
||||
llvm::StringRef command, const FileSpec &working_dir, int *status_ptr,
|
||||
int *signo_ptr, std::string *command_output,
|
||||
const Timeout<std::micro> &timeout) {
|
||||
std::string *separated_error_output, const Timeout<std::micro> &timeout) {
|
||||
return RunShellCommand(llvm::StringRef(), command, working_dir, status_ptr,
|
||||
signo_ptr, command_output, timeout);
|
||||
signo_ptr, command_output, separated_error_output,
|
||||
timeout);
|
||||
}
|
||||
|
||||
Status RemoteAwarePlatform::RunShellCommand(
|
||||
llvm::StringRef shell, llvm::StringRef command, const FileSpec &working_dir,
|
||||
int *status_ptr, int *signo_ptr, std::string *command_output,
|
||||
const Timeout<std::micro> &timeout) {
|
||||
std::string *separated_error_output, const Timeout<std::micro> &timeout) {
|
||||
if (m_remote_platform_sp)
|
||||
return m_remote_platform_sp->RunShellCommand(shell, command, working_dir,
|
||||
status_ptr, signo_ptr,
|
||||
command_output, timeout);
|
||||
return m_remote_platform_sp->RunShellCommand(
|
||||
shell, command, working_dir, status_ptr, signo_ptr, command_output,
|
||||
separated_error_output, timeout);
|
||||
return Platform::RunShellCommand(shell, command, working_dir, status_ptr,
|
||||
signo_ptr, command_output, timeout);
|
||||
signo_ptr, command_output,
|
||||
separated_error_output, timeout);
|
||||
}
|
||||
|
||||
Status RemoteAwarePlatform::MakeDirectory(const FileSpec &file_spec,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user