[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:
Jason Molenda 2026-03-10 13:48:55 -07:00 committed by GitHub
parent 3829fdb8af
commit 1c228a0533
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 214 additions and 85 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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);
});
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;

View File

@ -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()) {

View File

@ -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;

View File

@ -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()) {

View File

@ -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

View File

@ -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>

View File

@ -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;

View File

@ -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:");

View File

@ -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);

View File

@ -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,");

View File

@ -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;
}

View File

@ -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");
}

View File

@ -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,