diff options
Diffstat (limited to 'simpleperf')
-rw-r--r-- | simpleperf/cmd_record_test.cpp | 17 | ||||
-rw-r--r-- | simpleperf/event_fd.cpp | 24 | ||||
-rw-r--r-- | simpleperf/event_fd.h | 9 | ||||
-rw-r--r-- | simpleperf/event_selection_set.cpp | 18 | ||||
-rw-r--r-- | simpleperf/event_type.cpp | 3 | ||||
-rw-r--r-- | simpleperf/event_type_table.h | 14 | ||||
-rwxr-xr-x | simpleperf/generate_event_type_table.py | 2 | ||||
-rw-r--r-- | simpleperf/workload.cpp | 12 | ||||
-rw-r--r-- | simpleperf/workload.h | 9 |
9 files changed, 70 insertions, 38 deletions
diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp index eddccfcc..c513e2e7 100644 --- a/simpleperf/cmd_record_test.cpp +++ b/simpleperf/cmd_record_test.cpp @@ -85,10 +85,17 @@ TEST(record_cmd, tracepoint_event) { ASSERT_TRUE(RecordCmd()->Run({"-a", "-e", "sched:sched_switch", "sleep", "1"})); } +extern bool IsBranchSamplingSupported(); + TEST(record_cmd, branch_sampling) { - ASSERT_TRUE(RecordCmd()->Run({"-a", "-b", "sleep", "1"})); - ASSERT_TRUE(RecordCmd()->Run({"-j", "any,any_call,any_ret,ind_call", "sleep", "1"})); - ASSERT_TRUE(RecordCmd()->Run({"-j", "any,k", "sleep", "1"})); - ASSERT_TRUE(RecordCmd()->Run({"-j", "any,u", "sleep", "1"})); - ASSERT_FALSE(RecordCmd()->Run({"-j", "u", "sleep", "1"})); + if (IsBranchSamplingSupported()) { + ASSERT_TRUE(RecordCmd()->Run({"-a", "-b", "sleep", "1"})); + ASSERT_TRUE(RecordCmd()->Run({"-j", "any,any_call,any_ret,ind_call", "sleep", "1"})); + ASSERT_TRUE(RecordCmd()->Run({"-j", "any,k", "sleep", "1"})); + ASSERT_TRUE(RecordCmd()->Run({"-j", "any,u", "sleep", "1"})); + ASSERT_FALSE(RecordCmd()->Run({"-j", "u", "sleep", "1"})); + } else { + GTEST_LOG_(INFO) + << "This test does nothing as branch stack sampling is not supported on this device."; + } } diff --git a/simpleperf/event_fd.cpp b/simpleperf/event_fd.cpp index f0a1ad56..b342ab5a 100644 --- a/simpleperf/event_fd.cpp +++ b/simpleperf/event_fd.cpp @@ -38,15 +38,18 @@ static int perf_event_open(perf_event_attr* attr, pid_t pid, int cpu, int group_ return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); } -std::unique_ptr<EventFd> EventFd::OpenEventFileForProcess(const perf_event_attr& attr, pid_t pid) { - return OpenEventFile(attr, pid, -1); +std::unique_ptr<EventFd> EventFd::OpenEventFileForProcess(const perf_event_attr& attr, pid_t pid, + bool report_error) { + return OpenEventFile(attr, pid, -1, report_error); } -std::unique_ptr<EventFd> EventFd::OpenEventFileForCpu(const perf_event_attr& attr, int cpu) { - return OpenEventFile(attr, -1, cpu); +std::unique_ptr<EventFd> EventFd::OpenEventFileForCpu(const perf_event_attr& attr, int cpu, + bool report_error) { + return OpenEventFile(attr, -1, cpu, report_error); } -std::unique_ptr<EventFd> EventFd::OpenEventFile(const perf_event_attr& attr, pid_t pid, int cpu) { +std::unique_ptr<EventFd> EventFd::OpenEventFile(const perf_event_attr& attr, pid_t pid, int cpu, + bool report_error) { perf_event_attr perf_attr = attr; std::string event_name = "unknown event"; const EventType* event_type = @@ -56,15 +59,14 @@ std::unique_ptr<EventFd> EventFd::OpenEventFile(const perf_event_attr& attr, pid } int perf_event_fd = perf_event_open(&perf_attr, pid, cpu, -1, 0); if (perf_event_fd == -1) { - // It depends whether the perf_event_file configuration is supported by the kernel and the - // machine. So fail to open the file is not an error. - PLOG(DEBUG) << "open perf_event_file (event " << event_name << ", pid " << pid << ", cpu " - << cpu << ") failed"; + (report_error ? PLOG(ERROR) : PLOG(DEBUG)) << "open perf_event_file (event " << event_name + << ", pid " << pid << ", cpu " << cpu << ") failed"; return nullptr; } if (fcntl(perf_event_fd, F_SETFD, FD_CLOEXEC) == -1) { - PLOG(ERROR) << "fcntl(FD_CLOEXEC) for perf_event_file (event " << event_name << ", pid " << pid - << ", cpu " << cpu << ") failed"; + (report_error ? PLOG(ERROR) : PLOG(DEBUG)) << "fcntl(FD_CLOEXEC) for perf_event_file (event " + << event_name << ", pid " << pid << ", cpu " << cpu + << ") failed"; return nullptr; } return std::unique_ptr<EventFd>(new EventFd(perf_event_fd, event_name, pid, cpu)); diff --git a/simpleperf/event_fd.h b/simpleperf/event_fd.h index 36ea0cb0..e05761e2 100644 --- a/simpleperf/event_fd.h +++ b/simpleperf/event_fd.h @@ -37,9 +37,12 @@ struct PerfCounter { // EventFd represents an opened perf_event_file. class EventFd { public: - static std::unique_ptr<EventFd> OpenEventFileForProcess(const perf_event_attr& attr, pid_t pid); - static std::unique_ptr<EventFd> OpenEventFileForCpu(const perf_event_attr& attr, int cpu); - static std::unique_ptr<EventFd> OpenEventFile(const perf_event_attr& attr, pid_t pid, int cpu); + static std::unique_ptr<EventFd> OpenEventFileForProcess(const perf_event_attr& attr, pid_t pid, + bool report_error = true); + static std::unique_ptr<EventFd> OpenEventFileForCpu(const perf_event_attr& attr, int cpu, + bool report_error = true); + static std::unique_ptr<EventFd> OpenEventFile(const perf_event_attr& attr, pid_t pid, int cpu, + bool report_error = true); ~EventFd(); diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp index 6f14b804..644938c1 100644 --- a/simpleperf/event_selection_set.cpp +++ b/simpleperf/event_selection_set.cpp @@ -22,6 +22,18 @@ #include "event_attr.h" #include "event_type.h" +bool IsBranchSamplingSupported() { + const EventType* event_type = EventTypeFactory::FindEventTypeByName("cpu-cycles", false); + if (event_type == nullptr) { + return false; + } + perf_event_attr attr = CreateDefaultPerfEventAttr(*event_type); + attr.sample_type |= PERF_SAMPLE_BRANCH_STACK; + attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY; + auto event_fd = EventFd::OpenEventFileForProcess(attr, getpid(), false); + return event_fd != nullptr; +} + void EventSelectionSet::AddEventType(const EventType& event_type) { EventSelection selection; selection.event_type = &event_type; @@ -64,6 +76,10 @@ bool EventSelectionSet::SetBranchSampling(uint64_t branch_sample_type) { LOG(ERROR) << "Invalid branch_sample_type: 0x" << std::hex << branch_sample_type; return false; } + if (branch_sample_type != 0 && !IsBranchSamplingSupported()) { + LOG(ERROR) << "branch stack sampling is not supported on this device."; + return false; + } for (auto& selection : selections_) { perf_event_attr& attr = selection.event_attr; if (branch_sample_type != 0) { @@ -103,8 +119,6 @@ bool EventSelectionSet::OpenEventFilesForProcess(pid_t pid) { for (auto& selection : selections_) { auto event_fd = EventFd::OpenEventFileForProcess(selection.event_attr, pid); if (event_fd == nullptr) { - PLOG(ERROR) << "failed to open perf event file for event type " << selection.event_type->name - << " on pid " << pid; return false; } selection.event_fds.push_back(std::move(event_fd)); diff --git a/simpleperf/event_type.cpp b/simpleperf/event_type.cpp index a3b8fd2e..e4c50e1b 100644 --- a/simpleperf/event_type.cpp +++ b/simpleperf/event_type.cpp @@ -37,7 +37,8 @@ static const std::vector<EventType> static_event_type_array = { }; static bool IsEventTypeSupportedByKernel(const EventType& event_type) { - auto event_fd = EventFd::OpenEventFileForProcess(CreateDefaultPerfEventAttr(event_type), getpid()); + auto event_fd = + EventFd::OpenEventFileForProcess(CreateDefaultPerfEventAttr(event_type), getpid(), false); return event_fd != nullptr; } diff --git a/simpleperf/event_type_table.h b/simpleperf/event_type_table.h index 895cc85b..a77be0af 100644 --- a/simpleperf/event_type_table.h +++ b/simpleperf/event_type_table.h @@ -20,43 +20,43 @@ {"alignment-faults", PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS}, {"emulation-faults", PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS}, -{"L1-dcache-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, +{"L1-dcache-loads", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"L1-dcache-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"L1-dcache-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"L1-dcache-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"L1-dcache-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"L1-dcache-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, -{"L1-icache-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, +{"L1-icache-loads", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"L1-icache-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"L1-icache-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"L1-icache-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"L1-icache-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"L1-icache-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, -{"LLC-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, +{"LLC-loads", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"LLC-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"LLC-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"LLC-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"LLC-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"LLC-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, -{"dTLB-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, +{"dTLB-loads", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"dTLB-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"dTLB-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"dTLB-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"dTLB-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"dTLB-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, -{"iTLB-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, +{"iTLB-loads", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"iTLB-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"iTLB-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"iTLB-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"iTLB-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"iTLB-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, -{"branch-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, +{"branch-loads", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"branch-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"branch-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"branch-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"branch-prefetches", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"branch-prefetch-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, -{"node-loades", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_NODE) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, +{"node-loads", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_NODE) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"node-load-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_NODE) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, {"node-stores", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_NODE) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16))}, {"node-store-misses", PERF_TYPE_HW_CACHE, ((PERF_COUNT_HW_CACHE_NODE) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16))}, diff --git a/simpleperf/generate_event_type_table.py b/simpleperf/generate_event_type_table.py index b3fb897c..9fbd278c 100755 --- a/simpleperf/generate_event_type_table.py +++ b/simpleperf/generate_event_type_table.py @@ -81,7 +81,7 @@ def gen_hw_cache_events(): ["branch", "PERF_COUNT_HW_CACHE_BPU"], ["node", "PERF_COUNT_HW_CACHE_NODE"], ] - hw_cache_ops = [["loades", "load", "PERF_COUNT_HW_CACHE_OP_READ"], + hw_cache_ops = [["loads", "load", "PERF_COUNT_HW_CACHE_OP_READ"], ["stores", "store", "PERF_COUNT_HW_CACHE_OP_WRITE"], ["prefetches", "prefetch", "PERF_COUNT_HW_CACHE_OP_PREFETCH"], diff --git a/simpleperf/workload.cpp b/simpleperf/workload.cpp index 9d395cb1..2364b1c4 100644 --- a/simpleperf/workload.cpp +++ b/simpleperf/workload.cpp @@ -31,6 +31,18 @@ std::unique_ptr<Workload> Workload::CreateWorkload(const std::vector<std::string return nullptr; } +Workload::~Workload() { + if (work_pid_ != -1 && work_state_ != NotYetCreateNewProcess && work_state_ != Finished) { + kill(work_pid_, SIGKILL); + } + if (start_signal_fd_ != -1) { + close(start_signal_fd_); + } + if (exec_child_fd_ != -1) { + close(exec_child_fd_); + } +} + static void ChildProcessFn(std::vector<std::string>& args, int start_signal_fd, int exec_child_fd); bool Workload::CreateNewProcess() { diff --git a/simpleperf/workload.h b/simpleperf/workload.h index 57622c8a..9e2f0db6 100644 --- a/simpleperf/workload.h +++ b/simpleperf/workload.h @@ -36,14 +36,7 @@ class Workload { public: static std::unique_ptr<Workload> CreateWorkload(const std::vector<std::string>& args); - ~Workload() { - if (start_signal_fd_ != -1) { - close(start_signal_fd_); - } - if (exec_child_fd_ != -1) { - close(exec_child_fd_); - } - } + ~Workload(); bool Start(); bool IsFinished(); |