1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "environment.h" 18 19 #include <inttypes.h> 20 #include <signal.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <sys/resource.h> 24 #include <sys/utsname.h> 25 26 #include <limits> 27 #include <set> 28 #include <unordered_map> 29 #include <vector> 30 31 #include <android-base/file.h> 32 #include <android-base/logging.h> 33 #include <android-base/parseint.h> 34 #include <android-base/strings.h> 35 #include <android-base/stringprintf.h> 36 #include <procinfo/process.h> 37 38 #if defined(__ANDROID__) 39 #include <android-base/properties.h> 40 #endif 41 42 #include "event_type.h" 43 #include "IOEventLoop.h" 44 #include "read_elf.h" 45 #include "thread_tree.h" 46 #include "utils.h" 47 #include "workload.h" 48 49 class LineReader { 50 public: 51 explicit LineReader(FILE* fp) : fp_(fp), buf_(nullptr), bufsize_(0) { 52 } 53 54 ~LineReader() { 55 free(buf_); 56 fclose(fp_); 57 } 58 59 char* ReadLine() { 60 if (getline(&buf_, &bufsize_, fp_) != -1) { 61 return buf_; 62 } 63 return nullptr; 64 } 65 66 size_t MaxLineSize() { 67 return bufsize_; 68 } 69 70 private: 71 FILE* fp_; 72 char* buf_; 73 size_t bufsize_; 74 }; 75 76 std::vector<int> GetOnlineCpus() { 77 std::vector<int> result; 78 FILE* fp = fopen("/sys/devices/system/cpu/online", "re"); 79 if (fp == nullptr) { 80 PLOG(ERROR) << "can't open online cpu information"; 81 return result; 82 } 83 84 LineReader reader(fp); 85 char* line; 86 if ((line = reader.ReadLine()) != nullptr) { 87 result = GetCpusFromString(line); 88 } 89 CHECK(!result.empty()) << "can't get online cpu information"; 90 return result; 91 } 92 93 std::vector<int> GetCpusFromString(const std::string& s) { 94 std::set<int> cpu_set; 95 bool have_dash = false; 96 const char* p = s.c_str(); 97 char* endp; 98 int last_cpu; 99 int cpu; 100 // Parse line like: 0,1-3, 5, 7-8 101 while ((cpu = static_cast<int>(strtol(p, &endp, 10))) != 0 || endp != p) { 102 if (have_dash && !cpu_set.empty()) { 103 for (int t = last_cpu + 1; t < cpu; ++t) { 104 cpu_set.insert(t); 105 } 106 } 107 have_dash = false; 108 cpu_set.insert(cpu); 109 last_cpu = cpu; 110 p = endp; 111 while (!isdigit(*p) && *p != '\0') { 112 if (*p == '-') { 113 have_dash = true; 114 } 115 ++p; 116 } 117 } 118 return std::vector<int>(cpu_set.begin(), cpu_set.end()); 119 } 120 121 static std::vector<KernelMmap> GetLoadedModules() { 122 std::vector<KernelMmap> result; 123 FILE* fp = fopen("/proc/modules", "re"); 124 if (fp == nullptr) { 125 // There is no /proc/modules on Android devices, so we don't print error if failed to open it. 126 PLOG(DEBUG) << "failed to open file /proc/modules"; 127 return result; 128 } 129 LineReader reader(fp); 130 char* line; 131 while ((line = reader.ReadLine()) != nullptr) { 132 // Parse line like: nf_defrag_ipv6 34768 1 nf_conntrack_ipv6, Live 0xffffffffa0fe5000 133 char name[reader.MaxLineSize()]; 134 uint64_t addr; 135 uint64_t len; 136 if (sscanf(line, "%s%" PRIu64 "%*u%*s%*s 0x%" PRIx64, name, &len, &addr) == 3) { 137 KernelMmap map; 138 map.name = name; 139 map.start_addr = addr; 140 map.len = len; 141 result.push_back(map); 142 } 143 } 144 bool all_zero = true; 145 for (const auto& map : result) { 146 if (map.start_addr != 0) { 147 all_zero = false; 148 } 149 } 150 if (all_zero) { 151 LOG(DEBUG) << "addresses in /proc/modules are all zero, so ignore kernel modules"; 152 return std::vector<KernelMmap>(); 153 } 154 return result; 155 } 156 157 static void GetAllModuleFiles(const std::string& path, 158 std::unordered_map<std::string, std::string>* module_file_map) { 159 for (const auto& name : GetEntriesInDir(path)) { 160 std::string entry_path = path + "/" + name; 161 if (IsRegularFile(entry_path) && android::base::EndsWith(name, ".ko")) { 162 std::string module_name = name.substr(0, name.size() - 3); 163 std::replace(module_name.begin(), module_name.end(), '-', '_'); 164 module_file_map->insert(std::make_pair(module_name, entry_path)); 165 } else if (IsDir(entry_path)) { 166 GetAllModuleFiles(entry_path, module_file_map); 167 } 168 } 169 } 170 171 static std::vector<KernelMmap> GetModulesInUse() { 172 std::vector<KernelMmap> module_mmaps = GetLoadedModules(); 173 if (module_mmaps.empty()) { 174 return std::vector<KernelMmap>(); 175 } 176 std::unordered_map<std::string, std::string> module_file_map; 177 #if defined(__ANDROID__) 178 // Search directories listed in "File locations" section in 179 // https://source.android.com/devices/architecture/kernel/modular-kernels. 180 for (const auto& path : {"/vendor/lib/modules", "/odm/lib/modules", "/lib/modules"}) { 181 GetAllModuleFiles(path, &module_file_map); 182 } 183 #else 184 utsname uname_buf; 185 if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) { 186 PLOG(ERROR) << "uname() failed"; 187 return std::vector<KernelMmap>(); 188 } 189 std::string linux_version = uname_buf.release; 190 std::string module_dirpath = "/lib/modules/" + linux_version + "/kernel"; 191 GetAllModuleFiles(module_dirpath, &module_file_map); 192 #endif 193 for (auto& module : module_mmaps) { 194 auto it = module_file_map.find(module.name); 195 if (it != module_file_map.end()) { 196 module.filepath = it->second; 197 } 198 } 199 return module_mmaps; 200 } 201 202 void GetKernelAndModuleMmaps(KernelMmap* kernel_mmap, std::vector<KernelMmap>* module_mmaps) { 203 kernel_mmap->name = DEFAULT_KERNEL_MMAP_NAME; 204 kernel_mmap->start_addr = 0; 205 kernel_mmap->len = std::numeric_limits<uint64_t>::max(); 206 kernel_mmap->filepath = kernel_mmap->name; 207 *module_mmaps = GetModulesInUse(); 208 for (auto& map : *module_mmaps) { 209 if (map.filepath.empty()) { 210 map.filepath = "[" + map.name + "]"; 211 } 212 } 213 } 214 215 static bool ReadThreadNameAndPid(pid_t tid, std::string* comm, pid_t* pid) { 216 android::procinfo::ProcessInfo procinfo; 217 if (!android::procinfo::GetProcessInfo(tid, &procinfo)) { 218 return false; 219 } 220 if (comm != nullptr) { 221 *comm = procinfo.name; 222 } 223 if (pid != nullptr) { 224 *pid = procinfo.pid; 225 } 226 return true; 227 } 228 229 std::vector<pid_t> GetThreadsInProcess(pid_t pid) { 230 std::vector<pid_t> result; 231 android::procinfo::GetProcessTids(pid, &result); 232 return result; 233 } 234 235 bool IsThreadAlive(pid_t tid) { 236 return IsDir(android::base::StringPrintf("/proc/%d", tid)); 237 } 238 239 bool GetProcessForThread(pid_t tid, pid_t* pid) { 240 return ReadThreadNameAndPid(tid, nullptr, pid); 241 } 242 243 bool GetThreadName(pid_t tid, std::string* name) { 244 return ReadThreadNameAndPid(tid, name, nullptr); 245 } 246 247 std::vector<pid_t> GetAllProcesses() { 248 std::vector<pid_t> result; 249 std::vector<std::string> entries = GetEntriesInDir("/proc"); 250 for (const auto& entry : entries) { 251 pid_t pid; 252 if (!android::base::ParseInt(entry.c_str(), &pid, 0)) { 253 continue; 254 } 255 result.push_back(pid); 256 } 257 return result; 258 } 259 260 bool GetThreadMmapsInProcess(pid_t pid, std::vector<ThreadMmap>* thread_mmaps) { 261 std::string map_file = android::base::StringPrintf("/proc/%d/maps", pid); 262 FILE* fp = fopen(map_file.c_str(), "re"); 263 if (fp == nullptr) { 264 PLOG(DEBUG) << "can't open file " << map_file; 265 return false; 266 } 267 thread_mmaps->clear(); 268 LineReader reader(fp); 269 char* line; 270 while ((line = reader.ReadLine()) != nullptr) { 271 // Parse line like: 00400000-00409000 r-xp 00000000 fc:00 426998 /usr/lib/gvfs/gvfsd-http 272 uint64_t start_addr, end_addr, pgoff; 273 char type[reader.MaxLineSize()]; 274 char execname[reader.MaxLineSize()]; 275 strcpy(execname, ""); 276 if (sscanf(line, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %*x:%*x %*u %s\n", &start_addr, 277 &end_addr, type, &pgoff, execname) < 4) { 278 continue; 279 } 280 if (strcmp(execname, "") == 0) { 281 strcpy(execname, DEFAULT_EXECNAME_FOR_THREAD_MMAP); 282 } 283 ThreadMmap thread; 284 thread.start_addr = start_addr; 285 thread.len = end_addr - start_addr; 286 thread.pgoff = pgoff; 287 thread.name = execname; 288 thread.executable = (type[2] == 'x'); 289 thread_mmaps->push_back(thread); 290 } 291 return true; 292 } 293 294 bool GetKernelBuildId(BuildId* build_id) { 295 ElfStatus result = GetBuildIdFromNoteFile("/sys/kernel/notes", build_id); 296 if (result != ElfStatus::NO_ERROR) { 297 LOG(DEBUG) << "failed to read /sys/kernel/notes: " << result; 298 } 299 return result == ElfStatus::NO_ERROR; 300 } 301 302 bool GetModuleBuildId(const std::string& module_name, BuildId* build_id) { 303 std::string notefile = "/sys/module/" + module_name + "/notes/.note.gnu.build-id"; 304 return GetBuildIdFromNoteFile(notefile, build_id); 305 } 306 307 bool GetValidThreadsFromThreadString(const std::string& tid_str, std::set<pid_t>* tid_set) { 308 std::vector<std::string> strs = android::base::Split(tid_str, ","); 309 for (const auto& s : strs) { 310 int tid; 311 if (!android::base::ParseInt(s.c_str(), &tid, 0)) { 312 LOG(ERROR) << "Invalid tid '" << s << "'"; 313 return false; 314 } 315 if (!IsDir(android::base::StringPrintf("/proc/%d", tid))) { 316 LOG(ERROR) << "Non existing thread '" << tid << "'"; 317 return false; 318 } 319 tid_set->insert(tid); 320 } 321 return true; 322 } 323 324 /* 325 * perf event paranoia level: 326 * -1 - not paranoid at all 327 * 0 - disallow raw tracepoint access for unpriv 328 * 1 - disallow cpu events for unpriv 329 * 2 - disallow kernel profiling for unpriv 330 * 3 - disallow user profiling for unpriv 331 */ 332 static bool ReadPerfEventParanoid(int* value) { 333 std::string s; 334 if (!android::base::ReadFileToString("/proc/sys/kernel/perf_event_paranoid", &s)) { 335 PLOG(DEBUG) << "failed to read /proc/sys/kernel/perf_event_paranoid"; 336 return false; 337 } 338 s = android::base::Trim(s); 339 if (!android::base::ParseInt(s.c_str(), value)) { 340 PLOG(ERROR) << "failed to parse /proc/sys/kernel/perf_event_paranoid: " << s; 341 return false; 342 } 343 return true; 344 } 345 346 bool CanRecordRawData() { 347 int value; 348 return IsRoot() || (ReadPerfEventParanoid(&value) && value == -1); 349 } 350 351 static const char* GetLimitLevelDescription(int limit_level) { 352 switch (limit_level) { 353 case -1: return "unlimited"; 354 case 0: return "disallowing raw tracepoint access for unpriv"; 355 case 1: return "disallowing cpu events for unpriv"; 356 case 2: return "disallowing kernel profiling for unpriv"; 357 case 3: return "disallowing user profiling for unpriv"; 358 default: return "unknown level"; 359 } 360 } 361 362 bool CheckPerfEventLimit() { 363 // Root is not limited by /proc/sys/kernel/perf_event_paranoid. However, the monitored threads 364 // may create child processes not running as root. To make sure the child processes have 365 // enough permission to create inherited tracepoint events, write -1 to perf_event_paranoid. 366 // See http://b/62230699. 367 if (IsRoot() && android::base::WriteStringToFile("-1", "/proc/sys/kernel/perf_event_paranoid")) { 368 return true; 369 } 370 int limit_level; 371 bool can_read_paranoid = ReadPerfEventParanoid(&limit_level); 372 if (can_read_paranoid && limit_level <= 1) { 373 return true; 374 } 375 #if defined(__ANDROID__) 376 const std::string prop_name = "security.perf_harden"; 377 std::string prop_value = android::base::GetProperty(prop_name, ""); 378 if (prop_value.empty()) { 379 // can't do anything if there is no such property. 380 return true; 381 } 382 if (prop_value == "0") { 383 return true; 384 } 385 // Try to enable perf_event_paranoid by setprop security.perf_harden=0. 386 if (android::base::SetProperty(prop_name, "0")) { 387 sleep(1); 388 if (can_read_paranoid && ReadPerfEventParanoid(&limit_level) && limit_level <= 1) { 389 return true; 390 } 391 if (android::base::GetProperty(prop_name, "") == "0") { 392 return true; 393 } 394 } 395 if (can_read_paranoid) { 396 LOG(WARNING) << "/proc/sys/kernel/perf_event_paranoid is " << limit_level 397 << ", " << GetLimitLevelDescription(limit_level) << "."; 398 } 399 LOG(WARNING) << "Try using `adb shell setprop security.perf_harden 0` to allow profiling."; 400 return false; 401 #else 402 if (can_read_paranoid) { 403 LOG(WARNING) << "/proc/sys/kernel/perf_event_paranoid is " << limit_level 404 << ", " << GetLimitLevelDescription(limit_level) << "."; 405 return false; 406 } 407 #endif 408 return true; 409 } 410 411 bool GetMaxSampleFrequency(uint64_t* max_sample_freq) { 412 std::string s; 413 if (!android::base::ReadFileToString("/proc/sys/kernel/perf_event_max_sample_rate", &s)) { 414 PLOG(DEBUG) << "failed to read /proc/sys/kernel/perf_event_max_sample_rate"; 415 return false; 416 } 417 s = android::base::Trim(s); 418 if (!android::base::ParseUint(s.c_str(), max_sample_freq)) { 419 LOG(ERROR) << "failed to parse /proc/sys/kernel/perf_event_max_sample_rate: " << s; 420 return false; 421 } 422 return true; 423 } 424 425 bool CheckKernelSymbolAddresses() { 426 const std::string kptr_restrict_file = "/proc/sys/kernel/kptr_restrict"; 427 std::string s; 428 if (!android::base::ReadFileToString(kptr_restrict_file, &s)) { 429 PLOG(DEBUG) << "failed to read " << kptr_restrict_file; 430 return false; 431 } 432 s = android::base::Trim(s); 433 int value; 434 if (!android::base::ParseInt(s.c_str(), &value)) { 435 LOG(ERROR) << "failed to parse " << kptr_restrict_file << ": " << s; 436 return false; 437 } 438 // Accessible to everyone? 439 if (value == 0) { 440 return true; 441 } 442 // Accessible to root? 443 if (value == 1 && IsRoot()) { 444 return true; 445 } 446 // Can we make it accessible to us? 447 if (IsRoot() && android::base::WriteStringToFile("1", kptr_restrict_file)) { 448 return true; 449 } 450 LOG(WARNING) << "Access to kernel symbol addresses is restricted. If " 451 << "possible, please do `echo 0 >/proc/sys/kernel/kptr_restrict` " 452 << "to fix this."; 453 return false; 454 } 455 456 ArchType GetMachineArch() { 457 utsname uname_buf; 458 if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) { 459 PLOG(WARNING) << "uname() failed"; 460 return GetBuildArch(); 461 } 462 ArchType arch = GetArchType(uname_buf.machine); 463 if (arch != ARCH_UNSUPPORTED) { 464 return arch; 465 } 466 return GetBuildArch(); 467 } 468 469 void PrepareVdsoFile() { 470 // vdso is an elf file in memory loaded in each process's user space by the kernel. To read 471 // symbols from it and unwind through it, we need to dump it into a file in storage. 472 // It doesn't affect much when failed to prepare vdso file, so there is no need to return values. 473 std::vector<ThreadMmap> thread_mmaps; 474 if (!GetThreadMmapsInProcess(getpid(), &thread_mmaps)) { 475 return; 476 } 477 const ThreadMmap* vdso_map = nullptr; 478 for (const auto& map : thread_mmaps) { 479 if (map.name == "[vdso]") { 480 vdso_map = ↦ 481 break; 482 } 483 } 484 if (vdso_map == nullptr) { 485 return; 486 } 487 std::string s(vdso_map->len, '\0'); 488 memcpy(&s[0], reinterpret_cast<void*>(static_cast<uintptr_t>(vdso_map->start_addr)), 489 vdso_map->len); 490 std::unique_ptr<TemporaryFile> tmpfile = ScopedTempFiles::CreateTempFile(); 491 if (!android::base::WriteStringToFd(s, tmpfile->release())) { 492 return; 493 } 494 Dso::SetVdsoFile(tmpfile->path, sizeof(size_t) == sizeof(uint64_t)); 495 } 496 497 static bool HasOpenedAppApkFile(int pid) { 498 std::string fd_path = "/proc/" + std::to_string(pid) + "/fd/"; 499 std::vector<std::string> files = GetEntriesInDir(fd_path); 500 for (const auto& file : files) { 501 std::string real_path; 502 if (!android::base::Readlink(fd_path + file, &real_path)) { 503 continue; 504 } 505 if (real_path.find("app") != std::string::npos && real_path.find(".apk") != std::string::npos) { 506 return true; 507 } 508 } 509 return false; 510 } 511 512 std::set<pid_t> WaitForAppProcesses(const std::string& package_name) { 513 std::set<pid_t> result; 514 size_t loop_count = 0; 515 while (true) { 516 std::vector<pid_t> pids = GetAllProcesses(); 517 for (pid_t pid : pids) { 518 std::string cmdline; 519 if (!android::base::ReadFileToString("/proc/" + std::to_string(pid) + "/cmdline", &cmdline)) { 520 // Maybe we don't have permission to read it. 521 continue; 522 } 523 std::string process_name = android::base::Basename(cmdline); 524 // The app may have multiple processes, with process name like 525 // com.google.android.googlequicksearchbox:search. 526 size_t split_pos = process_name.find(':'); 527 if (split_pos != std::string::npos) { 528 process_name = process_name.substr(0, split_pos); 529 } 530 if (process_name != package_name) { 531 continue; 532 } 533 // If a debuggable app with wrap.sh runs on Android O, the app will be started with 534 // logwrapper as below: 535 // 1. Zygote forks a child process, rename it to package_name. 536 // 2. The child process execute sh, which starts a child process running 537 // /system/bin/logwrapper. 538 // 3. logwrapper starts a child process running sh, which interprets wrap.sh. 539 // 4. wrap.sh starts a child process running the app. 540 // The problem here is we want to profile the process started in step 4, but sometimes we 541 // run into the process started in step 1. To solve it, we can check if the process has 542 // opened an apk file in some app dirs. 543 if (!HasOpenedAppApkFile(pid)) { 544 continue; 545 } 546 if (loop_count > 0u) { 547 LOG(INFO) << "Got process " << pid << " for package " << package_name; 548 } 549 result.insert(pid); 550 } 551 if (!result.empty()) { 552 return result; 553 } 554 if (++loop_count == 1u) { 555 LOG(INFO) << "Waiting for process of app " << package_name; 556 } 557 usleep(1000); 558 } 559 } 560 561 class ScopedFile { 562 public: 563 ScopedFile(const std::string& filepath, const std::string& app_package_name = "") 564 : filepath_(filepath), app_package_name_(app_package_name) {} 565 566 ~ScopedFile() { 567 if (app_package_name_.empty()) { 568 unlink(filepath_.c_str()); 569 } else { 570 Workload::RunCmd({"run-as", app_package_name_, "rm", "-rf", filepath_}); 571 } 572 } 573 574 private: 575 std::string filepath_; 576 std::string app_package_name_; 577 }; 578 579 bool RunInAppContext(const std::string& app_package_name, const std::string& cmd, 580 const std::vector<std::string>& args, size_t workload_args_size, 581 const std::string& output_filepath, bool need_tracepoint_events) { 582 // 1. Test if the package exists. 583 if (!Workload::RunCmd({"run-as", app_package_name, "echo", ">/dev/null"}, false)) { 584 LOG(ERROR) << "Package " << app_package_name << " doesn't exist or isn't debuggable."; 585 return false; 586 } 587 588 // 2. Copy simpleperf binary to the package. Create tracepoint_file if needed. 589 std::string simpleperf_path; 590 if (!android::base::Readlink("/proc/self/exe", &simpleperf_path)) { 591 PLOG(ERROR) << "ReadLink failed"; 592 return false; 593 } 594 if (!Workload::RunCmd({"run-as", app_package_name, "cp", simpleperf_path, "simpleperf"})) { 595 return false; 596 } 597 ScopedFile scoped_simpleperf("simpleperf", app_package_name); 598 std::unique_ptr<ScopedFile> scoped_tracepoint_file; 599 const std::string tracepoint_file = "/data/local/tmp/tracepoint_events"; 600 if (need_tracepoint_events) { 601 // Since we can't read tracepoint events from tracefs in app's context, we need to prepare 602 // them in tracepoint_file in shell's context, and pass the path of tracepoint_file to the 603 // child process using --tracepoint-events option. 604 if (!android::base::WriteStringToFile(GetTracepointEvents(), tracepoint_file)) { 605 PLOG(ERROR) << "Failed to store tracepoint events"; 606 return false; 607 } 608 scoped_tracepoint_file.reset(new ScopedFile(tracepoint_file)); 609 } 610 611 // 3. Prepare to start child process to profile. 612 std::string output_basename = output_filepath.empty() ? "" : 613 android::base::Basename(output_filepath); 614 std::vector<std::string> new_args = 615 {"run-as", app_package_name, "./simpleperf", cmd, "--in-app", "--log", GetLogSeverityName()}; 616 if (need_tracepoint_events) { 617 new_args.push_back("--tracepoint-events"); 618 new_args.push_back(tracepoint_file); 619 } 620 for (size_t i = 0; i < args.size(); ++i) { 621 if (i >= args.size() - workload_args_size || args[i] != "-o") { 622 new_args.push_back(args[i]); 623 } else { 624 new_args.push_back(args[i++]); 625 new_args.push_back(output_basename); 626 } 627 } 628 std::unique_ptr<Workload> workload = Workload::CreateWorkload(new_args); 629 if (!workload) { 630 return false; 631 } 632 633 IOEventLoop loop; 634 bool need_to_kill_child = false; 635 if (!loop.AddSignalEvents({SIGINT, SIGTERM, SIGHUP}, 636 [&]() { need_to_kill_child = true; return loop.ExitLoop(); })) { 637 return false; 638 } 639 if (!loop.AddSignalEvent(SIGCHLD, [&]() { return loop.ExitLoop(); })) { 640 return false; 641 } 642 643 // 4. Create child process to run run-as, and wait for the child process. 644 if (!workload->Start()) { 645 return false; 646 } 647 if (!loop.RunLoop()) { 648 return false; 649 } 650 if (need_to_kill_child) { 651 // The child process can exit before we kill it, so don't report kill errors. 652 Workload::RunCmd({"run-as", app_package_name, "pkill", "simpleperf"}, false); 653 } 654 int exit_code; 655 if (!workload->WaitChildProcess(&exit_code) || exit_code != 0) { 656 return false; 657 } 658 659 // 5. If there is any output file, copy it from the app's directory. 660 if (!output_filepath.empty()) { 661 if (!Workload::RunCmd({"run-as", app_package_name, "cat", output_basename, 662 ">" + output_filepath})) { 663 return false; 664 } 665 if (!Workload::RunCmd({"run-as", app_package_name, "rm", output_basename})) { 666 return false; 667 } 668 } 669 return true; 670 } 671 672 static std::string default_package_name; 673 674 void SetDefaultAppPackageName(const std::string& package_name) { 675 default_package_name = package_name; 676 } 677 678 const std::string& GetDefaultAppPackageName() { 679 return default_package_name; 680 } 681 682 void AllowMoreOpenedFiles() { 683 // On Android <= O, the hard limit is 4096, and the soft limit is 1024. 684 // On Android >= P, both the hard and soft limit are 32768. 685 rlimit limit; 686 if (getrlimit(RLIMIT_NOFILE, &limit) == 0) { 687 limit.rlim_cur = limit.rlim_max; 688 setrlimit(RLIMIT_NOFILE, &limit); 689 } 690 } 691 692 std::string ScopedTempFiles::tmp_dir_; 693 std::vector<std::string> ScopedTempFiles::files_to_delete_; 694 695 ScopedTempFiles::ScopedTempFiles(const std::string& tmp_dir) { 696 CHECK(tmp_dir_.empty()); // No other ScopedTempFiles. 697 tmp_dir_ = tmp_dir; 698 } 699 700 ScopedTempFiles::~ScopedTempFiles() { 701 tmp_dir_.clear(); 702 for (auto& file : files_to_delete_) { 703 unlink(file.c_str()); 704 } 705 files_to_delete_.clear(); 706 } 707 708 std::unique_ptr<TemporaryFile> ScopedTempFiles::CreateTempFile(bool delete_in_destructor) { 709 CHECK(!tmp_dir_.empty()); 710 std::unique_ptr<TemporaryFile> tmp_file(new TemporaryFile(tmp_dir_)); 711 CHECK_NE(tmp_file->fd, -1); 712 if (delete_in_destructor) { 713 files_to_delete_.push_back(tmp_file->path); 714 } 715 return tmp_file; 716 } 717 718 bool SignalIsIgnored(int signo) { 719 struct sigaction act; 720 if (sigaction(signo, nullptr, &act) != 0) { 721 PLOG(FATAL) << "failed to query signal handler for signal " << signo; 722 } 723 724 if ((act.sa_flags & SA_SIGINFO)) { 725 return false; 726 } 727 728 return act.sa_handler == SIG_IGN; 729 } 730