#include "src/profiling/symbolizer/subprocess.h"
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <sstream>
#include <string>
#include <Windows.h>
#include "perfetto/base/logging.h"
namespace perfetto {
namespace profiling {
Subprocess::Subprocess(const std::string& file, std::vector<std::string> args) {
std::stringstream cmd;
cmd << file;
for (auto arg : args) {
cmd << " " << arg;
}
SECURITY_ATTRIBUTES attr;
attr.nLength = sizeof(SECURITY_ATTRIBUTES);
attr.bInheritHandle = true;
attr.lpSecurityDescriptor = nullptr;
if (!CreatePipe(&child_pipe_out_read_, &child_pipe_out_write_, &attr, 0) ||
!SetHandleInformation(child_pipe_out_read_, HANDLE_FLAG_INHERIT, 0)) {
PERFETTO_ELOG("Failed to create stdout pipe");
return;
}
if (!CreatePipe(&child_pipe_in_read_, &child_pipe_in_write_, &attr, 0) ||
!SetHandleInformation(child_pipe_in_write_, HANDLE_FLAG_INHERIT, 0)) {
PERFETTO_ELOG("Failed to create stdin pipe");
return;
}
PROCESS_INFORMATION proc_info;
STARTUPINFOA start_info;
bool success = false;
ZeroMemory(&proc_info, sizeof(PROCESS_INFORMATION));
ZeroMemory(&start_info, sizeof(STARTUPINFOA));
start_info.cb = sizeof(STARTUPINFOA);
start_info.hStdError = child_pipe_out_write_;
start_info.hStdOutput = child_pipe_out_write_;
start_info.hStdInput = child_pipe_in_read_;
start_info.dwFlags |= STARTF_USESTDHANDLES;
success = CreateProcessA(nullptr,
&(cmd.str()[0]),
nullptr,
nullptr,
TRUE,
0,
nullptr,
nullptr,
&start_info,
&proc_info);
if (success) {
CloseHandle(proc_info.hProcess);
CloseHandle(proc_info.hThread);
CloseHandle(child_pipe_out_write_);
CloseHandle(child_pipe_in_read_);
} else {
PERFETTO_ELOG("Failed to launch: %s", cmd.str().c_str());
child_pipe_in_read_ = nullptr;
child_pipe_in_write_ = nullptr;
child_pipe_out_write_ = nullptr;
child_pipe_out_read_ = nullptr;
}
}
Subprocess::~Subprocess() {
CloseHandle(child_pipe_out_read_);
CloseHandle(child_pipe_in_write_);
}
int64_t Subprocess::Write(const char* buffer, size_t size) {
if (child_pipe_in_write_ == nullptr) {
return -1;
}
DWORD bytes_written;
if (WriteFile(child_pipe_in_write_, buffer, static_cast<DWORD>(size),
&bytes_written, nullptr)) {
return static_cast<int64_t>(bytes_written);
}
return -1;
}
int64_t Subprocess::Read(char* buffer, size_t size) {
if (child_pipe_out_read_ == nullptr) {
return -1;
}
DWORD bytes_read;
if (ReadFile(child_pipe_out_read_, buffer, static_cast<DWORD>(size),
&bytes_read, nullptr)) {
return static_cast<int64_t>(bytes_read);
}
return -1;
}
}
}
#endif