| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/process/launch.h" | 5 #include "base/process/launch.h" |
| 6 | 6 |
| 7 #include <dirent.h> | 7 #include <dirent.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <sched.h> | 10 #include <sched.h> |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 // glibc's sigaction() will prevent access to sa_restorer, so we need to roll | 145 // glibc's sigaction() will prevent access to sa_restorer, so we need to roll |
| 146 // our own. | 146 // our own. |
| 147 int sys_rt_sigaction(int sig, const struct kernel_sigaction* act, | 147 int sys_rt_sigaction(int sig, const struct kernel_sigaction* act, |
| 148 struct kernel_sigaction* oact) { | 148 struct kernel_sigaction* oact) { |
| 149 return syscall(SYS_rt_sigaction, sig, act, oact, sizeof(kernel_sigset_t)); | 149 return syscall(SYS_rt_sigaction, sig, act, oact, sizeof(kernel_sigset_t)); |
| 150 } | 150 } |
| 151 | 151 |
| 152 // This function is intended to be used in between fork() and execve() and will | 152 // This function is intended to be used in between fork() and execve() and will |
| 153 // reset all signal handlers to the default. | 153 // reset all signal handlers to the default. |
| 154 // The motivation for going through all of them is that sa_restorer can leak | 154 // The motivation for going through all of them is that sa_restorer can leak |
| 155 // from parents and help defeat ASLR on buggy kernels. We reset it to NULL. | 155 // from parents and help defeat ASLR on buggy kernels. We reset it to null. |
| 156 // See crbug.com/177956. | 156 // See crbug.com/177956. |
| 157 void ResetChildSignalHandlersToDefaults(void) { | 157 void ResetChildSignalHandlersToDefaults(void) { |
| 158 for (int signum = 1; ; ++signum) { | 158 for (int signum = 1; ; ++signum) { |
| 159 struct kernel_sigaction act = {0}; | 159 struct kernel_sigaction act = {0}; |
| 160 int sigaction_get_ret = sys_rt_sigaction(signum, NULL, &act); | 160 int sigaction_get_ret = sys_rt_sigaction(signum, nullptr, &act); |
| 161 if (sigaction_get_ret && errno == EINVAL) { | 161 if (sigaction_get_ret && errno == EINVAL) { |
| 162 #if !defined(NDEBUG) | 162 #if !defined(NDEBUG) |
| 163 // Linux supports 32 real-time signals from 33 to 64. | 163 // Linux supports 32 real-time signals from 33 to 64. |
| 164 // If the number of signals in the Linux kernel changes, someone should | 164 // If the number of signals in the Linux kernel changes, someone should |
| 165 // look at this code. | 165 // look at this code. |
| 166 const int kNumberOfSignals = 64; | 166 const int kNumberOfSignals = 64; |
| 167 RAW_CHECK(signum == kNumberOfSignals + 1); | 167 RAW_CHECK(signum == kNumberOfSignals + 1); |
| 168 #endif // !defined(NDEBUG) | 168 #endif // !defined(NDEBUG) |
| 169 break; | 169 break; |
| 170 } | 170 } |
| 171 // All other failures are fatal. | 171 // All other failures are fatal. |
| 172 if (sigaction_get_ret) { | 172 if (sigaction_get_ret) { |
| 173 RAW_LOG(FATAL, "sigaction (get) failed."); | 173 RAW_LOG(FATAL, "sigaction (get) failed."); |
| 174 } | 174 } |
| 175 | 175 |
| 176 // The kernel won't allow to re-set SIGKILL or SIGSTOP. | 176 // The kernel won't allow to re-set SIGKILL or SIGSTOP. |
| 177 if (signum != SIGSTOP && signum != SIGKILL) { | 177 if (signum != SIGSTOP && signum != SIGKILL) { |
| 178 act.k_sa_handler = reinterpret_cast<void*>(SIG_DFL); | 178 act.k_sa_handler = reinterpret_cast<void*>(SIG_DFL); |
| 179 act.k_sa_restorer = NULL; | 179 act.k_sa_restorer = nullptr; |
| 180 if (sys_rt_sigaction(signum, &act, NULL)) { | 180 if (sys_rt_sigaction(signum, &act, nullptr)) { |
| 181 RAW_LOG(FATAL, "sigaction (set) failed."); | 181 RAW_LOG(FATAL, "sigaction (set) failed."); |
| 182 } | 182 } |
| 183 } | 183 } |
| 184 #if !defined(NDEBUG) | 184 #if !defined(NDEBUG) |
| 185 // Now ask the kernel again and check that no restorer will leak. | 185 // Now ask the kernel again and check that no restorer will leak. |
| 186 if (sys_rt_sigaction(signum, NULL, &act) || act.k_sa_restorer) { | 186 if (sys_rt_sigaction(signum, nullptr, &act) || act.k_sa_restorer) { |
| 187 RAW_LOG(FATAL, "Cound not fix sa_restorer."); | 187 RAW_LOG(FATAL, "Cound not fix sa_restorer."); |
| 188 } | 188 } |
| 189 #endif // !defined(NDEBUG) | 189 #endif // !defined(NDEBUG) |
| 190 } | 190 } |
| 191 } | 191 } |
| 192 #endif // !defined(OS_LINUX) || | 192 #endif // !defined(OS_LINUX) || |
| 193 // (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__)) | 193 // (!defined(__i386__) && !defined(__x86_64__) && !defined(__arm__)) |
| 194 } // anonymous namespace | 194 } // anonymous namespace |
| 195 | 195 |
| 196 // Functor for |ScopedDIR| (below). | 196 // Functor for |ScopedDIR| (below). |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 | 298 |
| 299 InjectiveMultimap fd_shuffle1; | 299 InjectiveMultimap fd_shuffle1; |
| 300 InjectiveMultimap fd_shuffle2; | 300 InjectiveMultimap fd_shuffle2; |
| 301 fd_shuffle1.reserve(fd_shuffle_size); | 301 fd_shuffle1.reserve(fd_shuffle_size); |
| 302 fd_shuffle2.reserve(fd_shuffle_size); | 302 fd_shuffle2.reserve(fd_shuffle_size); |
| 303 | 303 |
| 304 std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]); | 304 std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]); |
| 305 for (size_t i = 0; i < argv.size(); i++) { | 305 for (size_t i = 0; i < argv.size(); i++) { |
| 306 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 306 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
| 307 } | 307 } |
| 308 argv_cstr[argv.size()] = NULL; | 308 argv_cstr[argv.size()] = nullptr; |
| 309 | 309 |
| 310 std::unique_ptr<char* []> new_environ; | 310 std::unique_ptr<char* []> new_environ; |
| 311 char* const empty_environ = NULL; | 311 char* const empty_environ = nullptr; |
| 312 char* const* old_environ = GetEnvironment(); | 312 char* const* old_environ = GetEnvironment(); |
| 313 if (options.clear_environ) | 313 if (options.clear_environ) |
| 314 old_environ = &empty_environ; | 314 old_environ = &empty_environ; |
| 315 if (!options.environ.empty()) | 315 if (!options.environ.empty()) |
| 316 new_environ = AlterEnvironment(old_environ, options.environ); | 316 new_environ = AlterEnvironment(old_environ, options.environ); |
| 317 | 317 |
| 318 sigset_t full_sigset; | 318 sigset_t full_sigset; |
| 319 sigfillset(&full_sigset); | 319 sigfillset(&full_sigset); |
| 320 const sigset_t orig_sigmask = SetSignalMask(full_sigset); | 320 const sigset_t orig_sigmask = SetSignalMask(full_sigset); |
| 321 | 321 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); | 423 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095); |
| 424 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); | 424 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC); |
| 425 memset(reinterpret_cast<void*>(malloc), 0xff, 8); | 425 memset(reinterpret_cast<void*>(malloc), 0xff, 8); |
| 426 #endif // 0 | 426 #endif // 0 |
| 427 | 427 |
| 428 #if defined(OS_CHROMEOS) | 428 #if defined(OS_CHROMEOS) |
| 429 if (options.ctrl_terminal_fd >= 0) { | 429 if (options.ctrl_terminal_fd >= 0) { |
| 430 // Set process' controlling terminal. | 430 // Set process' controlling terminal. |
| 431 if (HANDLE_EINTR(setsid()) != -1) { | 431 if (HANDLE_EINTR(setsid()) != -1) { |
| 432 if (HANDLE_EINTR( | 432 if (HANDLE_EINTR( |
| 433 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, NULL)) == -1) { | 433 ioctl(options.ctrl_terminal_fd, TIOCSCTTY, nullptr)) == -1) { |
| 434 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set"); | 434 RAW_LOG(WARNING, "ioctl(TIOCSCTTY), ctrl terminal not set"); |
| 435 } | 435 } |
| 436 } else { | 436 } else { |
| 437 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set"); | 437 RAW_LOG(WARNING, "setsid failed, ctrl terminal not set"); |
| 438 } | 438 } |
| 439 } | 439 } |
| 440 #endif // defined(OS_CHROMEOS) | 440 #endif // defined(OS_CHROMEOS) |
| 441 | 441 |
| 442 if (options.fds_to_remap) { | 442 if (options.fds_to_remap) { |
| 443 // Cannot use STL iterators here, since debug iterators use locks. | 443 // Cannot use STL iterators here, since debug iterators use locks. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 } | 504 } |
| 505 | 505 |
| 506 return Process(pid); | 506 return Process(pid); |
| 507 } | 507 } |
| 508 | 508 |
| 509 void RaiseProcessToHighPriority() { | 509 void RaiseProcessToHighPriority() { |
| 510 // On POSIX, we don't actually do anything here. We could try to nice() or | 510 // On POSIX, we don't actually do anything here. We could try to nice() or |
| 511 // setpriority() or sched_getscheduler, but these all require extra rights. | 511 // setpriority() or sched_getscheduler, but these all require extra rights. |
| 512 } | 512 } |
| 513 | 513 |
| 514 // Return value used by GetAppOutputInternal to encapsulate the various exit | |
| 515 // scenarios from the function. | |
| 516 enum GetAppOutputInternalResult { | |
| 517 EXECUTE_FAILURE, | |
| 518 EXECUTE_SUCCESS, | |
| 519 GOT_MAX_OUTPUT, | |
| 520 }; | |
| 521 | |
| 522 // Executes the application specified by |argv| and wait for it to exit. Stores | 514 // Executes the application specified by |argv| and wait for it to exit. Stores |
| 523 // the output (stdout) in |output|. If |do_search_path| is set, it searches the | 515 // the output (stdout) in |output|. If |do_search_path| is set, it searches the |
| 524 // path for the application; in that case, |envp| must be null, and it will use | 516 // path for the application; in that case, |envp| must be null, and it will use |
| 525 // the current environment. If |do_search_path| is false, |argv[0]| should fully | 517 // the current environment. If |do_search_path| is false, |argv[0]| should fully |
| 526 // specify the path of the application, and |envp| will be used as the | 518 // specify the path of the application, and |envp| will be used as the |
| 527 // environment. If |include_stderr| is true, includes stderr otherwise redirects | 519 // environment. If |include_stderr| is true, includes stderr otherwise redirects |
| 528 // it to /dev/null. | 520 // it to /dev/null. |
| 529 // If we successfully start the application and get all requested output, we | 521 // The return value of the function indicates success or failure. In the case of |
| 530 // return GOT_MAX_OUTPUT, or if there is a problem starting or exiting | 522 // success, the application exit code will be returned in |*exit_code|, which |
| 531 // the application we return RUN_FAILURE. Otherwise we return EXECUTE_SUCCESS. | 523 // should be checked to determine if the application ran successfully. |
| 532 // The GOT_MAX_OUTPUT return value exists so a caller that asks for limited | 524 static bool GetAppOutputInternal( |
| 533 // output can treat this as a success, despite having an exit code of SIG_PIPE | |
| 534 // due to us closing the output pipe. | |
| 535 // In the case of EXECUTE_SUCCESS, the application exit code will be returned | |
| 536 // in |*exit_code|, which should be checked to determine if the application | |
| 537 // ran successfully. | |
| 538 static GetAppOutputInternalResult GetAppOutputInternal( | |
| 539 const std::vector<std::string>& argv, | 525 const std::vector<std::string>& argv, |
| 540 char* const envp[], | 526 char* const envp[], |
| 541 bool include_stderr, | 527 bool include_stderr, |
| 542 std::string* output, | 528 std::string* output, |
| 543 size_t max_output, | |
| 544 bool do_search_path, | 529 bool do_search_path, |
| 545 int* exit_code) { | 530 int* exit_code) { |
| 546 // Doing a blocking wait for another command to finish counts as IO. | 531 // Doing a blocking wait for another command to finish counts as IO. |
| 547 base::ThreadRestrictions::AssertIOAllowed(); | 532 base::ThreadRestrictions::AssertIOAllowed(); |
| 548 // exit_code must be supplied so calling function can determine success. | 533 // exit_code must be supplied so calling function can determine success. |
| 549 DCHECK(exit_code); | 534 DCHECK(exit_code); |
| 550 *exit_code = EXIT_FAILURE; | 535 *exit_code = EXIT_FAILURE; |
| 551 | 536 |
| 552 int pipe_fd[2]; | 537 int pipe_fd[2]; |
| 553 pid_t pid; | 538 pid_t pid; |
| 554 InjectiveMultimap fd_shuffle1, fd_shuffle2; | 539 InjectiveMultimap fd_shuffle1, fd_shuffle2; |
| 555 std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]); | 540 std::unique_ptr<char* []> argv_cstr(new char*[argv.size() + 1]); |
| 556 | 541 |
| 557 fd_shuffle1.reserve(3); | 542 fd_shuffle1.reserve(3); |
| 558 fd_shuffle2.reserve(3); | 543 fd_shuffle2.reserve(3); |
| 559 | 544 |
| 560 // Either |do_search_path| should be false or |envp| should be null, but not | 545 // Either |do_search_path| should be false or |envp| should be null, but not |
| 561 // both. | 546 // both. |
| 562 DCHECK(!do_search_path ^ !envp); | 547 DCHECK(!do_search_path ^ !envp); |
| 563 | 548 |
| 564 if (pipe(pipe_fd) < 0) | 549 if (pipe(pipe_fd) < 0) |
| 565 return EXECUTE_FAILURE; | 550 return false; |
| 566 | 551 |
| 567 switch (pid = fork()) { | 552 switch (pid = fork()) { |
| 568 case -1: // error | 553 case -1: // error |
| 569 close(pipe_fd[0]); | 554 close(pipe_fd[0]); |
| 570 close(pipe_fd[1]); | 555 close(pipe_fd[1]); |
| 571 return EXECUTE_FAILURE; | 556 return false; |
| 572 case 0: // child | 557 case 0: // child |
| 573 { | 558 { |
| 574 // DANGER: no calls to malloc or locks are allowed from now on: | 559 // DANGER: no calls to malloc or locks are allowed from now on: |
| 575 // http://crbug.com/36678 | 560 // http://crbug.com/36678 |
| 576 | 561 |
| 577 #if defined(OS_MACOSX) | 562 #if defined(OS_MACOSX) |
| 578 RestoreDefaultExceptionHandler(); | 563 RestoreDefaultExceptionHandler(); |
| 579 #endif | 564 #endif |
| 580 | 565 |
| 581 // Obscure fork() rule: in the child, if you don't end up doing exec*(), | 566 // Obscure fork() rule: in the child, if you don't end up doing exec*(), |
| (...skipping 16 matching lines...) Expand all Loading... |
| 598 for (size_t i = 0; i < fd_shuffle1.size(); ++i) | 583 for (size_t i = 0; i < fd_shuffle1.size(); ++i) |
| 599 fd_shuffle2.push_back(fd_shuffle1[i]); | 584 fd_shuffle2.push_back(fd_shuffle1[i]); |
| 600 | 585 |
| 601 if (!ShuffleFileDescriptors(&fd_shuffle1)) | 586 if (!ShuffleFileDescriptors(&fd_shuffle1)) |
| 602 _exit(127); | 587 _exit(127); |
| 603 | 588 |
| 604 CloseSuperfluousFds(fd_shuffle2); | 589 CloseSuperfluousFds(fd_shuffle2); |
| 605 | 590 |
| 606 for (size_t i = 0; i < argv.size(); i++) | 591 for (size_t i = 0; i < argv.size(); i++) |
| 607 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 592 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
| 608 argv_cstr[argv.size()] = NULL; | 593 argv_cstr[argv.size()] = nullptr; |
| 609 if (do_search_path) | 594 if (do_search_path) |
| 610 execvp(argv_cstr[0], argv_cstr.get()); | 595 execvp(argv_cstr[0], argv_cstr.get()); |
| 611 else | 596 else |
| 612 execve(argv_cstr[0], argv_cstr.get(), envp); | 597 execve(argv_cstr[0], argv_cstr.get(), envp); |
| 613 _exit(127); | 598 _exit(127); |
| 614 } | 599 } |
| 615 default: // parent | 600 default: // parent |
| 616 { | 601 { |
| 617 // Close our writing end of pipe now. Otherwise later read would not | 602 // Close our writing end of pipe now. Otherwise later read would not |
| 618 // be able to detect end of child's output (in theory we could still | 603 // be able to detect end of child's output (in theory we could still |
| 619 // write to the pipe). | 604 // write to the pipe). |
| 620 close(pipe_fd[1]); | 605 close(pipe_fd[1]); |
| 621 | 606 |
| 622 output->clear(); | 607 output->clear(); |
| 623 char buffer[256]; | |
| 624 size_t output_buf_left = max_output; | |
| 625 ssize_t bytes_read = 1; // A lie to properly handle |max_output == 0| | |
| 626 // case in the logic below. | |
| 627 | 608 |
| 628 while (output_buf_left > 0) { | 609 while (true) { |
| 629 bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer, | 610 char buffer[256]; |
| 630 std::min(output_buf_left, sizeof(buffer)))); | 611 ssize_t bytes_read = |
| 612 HANDLE_EINTR(read(pipe_fd[0], buffer, sizeof(buffer))); |
| 631 if (bytes_read <= 0) | 613 if (bytes_read <= 0) |
| 632 break; | 614 break; |
| 633 output->append(buffer, bytes_read); | 615 output->append(buffer, bytes_read); |
| 634 output_buf_left -= static_cast<size_t>(bytes_read); | |
| 635 } | 616 } |
| 636 close(pipe_fd[0]); | 617 close(pipe_fd[0]); |
| 637 | 618 |
| 638 // Always wait for exit code (even if we know we'll declare | 619 // Always wait for exit code (even if we know we'll declare |
| 639 // GOT_MAX_OUTPUT). | 620 // GOT_MAX_OUTPUT). |
| 640 Process process(pid); | 621 Process process(pid); |
| 641 bool success = process.WaitForExit(exit_code); | 622 return process.WaitForExit(exit_code); |
| 642 | |
| 643 // If we stopped because we read as much as we wanted, we return | |
| 644 // GOT_MAX_OUTPUT (because the child may exit due to |SIGPIPE|). | |
| 645 if (!output_buf_left && bytes_read > 0) | |
| 646 return GOT_MAX_OUTPUT; | |
| 647 else if (success) | |
| 648 return EXECUTE_SUCCESS; | |
| 649 return EXECUTE_FAILURE; | |
| 650 } | 623 } |
| 651 } | 624 } |
| 652 } | 625 } |
| 653 | 626 |
| 654 bool GetAppOutput(const CommandLine& cl, std::string* output) { | 627 bool GetAppOutput(const CommandLine& cl, std::string* output) { |
| 655 return GetAppOutput(cl.argv(), output); | 628 return GetAppOutput(cl.argv(), output); |
| 656 } | 629 } |
| 657 | 630 |
| 658 bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) { | 631 bool GetAppOutput(const std::vector<std::string>& argv, std::string* output) { |
| 659 // Run |execve()| with the current environment and store "unlimited" data. | 632 // Run |execve()| with the current environment. |
| 660 int exit_code; | 633 int exit_code; |
| 661 GetAppOutputInternalResult result = GetAppOutputInternal( | 634 bool result = |
| 662 argv, NULL, false, output, std::numeric_limits<std::size_t>::max(), true, | 635 GetAppOutputInternal(argv, nullptr, false, output, true, &exit_code); |
| 663 &exit_code); | 636 return result && exit_code == EXIT_SUCCESS; |
| 664 return result == EXECUTE_SUCCESS && exit_code == EXIT_SUCCESS; | |
| 665 } | 637 } |
| 666 | 638 |
| 667 bool GetAppOutputAndError(const CommandLine& cl, std::string* output) { | 639 bool GetAppOutputAndError(const CommandLine& cl, std::string* output) { |
| 668 // Run |execve()| with the current environment and store "unlimited" data. | 640 // Run |execve()| with the current environment. |
| 669 int exit_code; | 641 int exit_code; |
| 670 GetAppOutputInternalResult result = GetAppOutputInternal( | 642 bool result = |
| 671 cl.argv(), NULL, true, output, std::numeric_limits<std::size_t>::max(), | 643 GetAppOutputInternal(cl.argv(), nullptr, true, output, true, &exit_code); |
| 672 true, &exit_code); | 644 return result && exit_code == EXIT_SUCCESS; |
| 673 return result == EXECUTE_SUCCESS && exit_code == EXIT_SUCCESS; | |
| 674 } | |
| 675 | |
| 676 // TODO(viettrungluu): Conceivably, we should have a timeout as well, so we | |
| 677 // don't hang if what we're calling hangs. | |
| 678 bool GetAppOutputRestricted(const CommandLine& cl, | |
| 679 std::string* output, size_t max_output) { | |
| 680 // Run |execve()| with the empty environment. | |
| 681 char* const empty_environ = NULL; | |
| 682 int exit_code; | |
| 683 GetAppOutputInternalResult result = GetAppOutputInternal( | |
| 684 cl.argv(), &empty_environ, false, output, max_output, false, &exit_code); | |
| 685 return result == GOT_MAX_OUTPUT || (result == EXECUTE_SUCCESS && | |
| 686 exit_code == EXIT_SUCCESS); | |
| 687 } | 645 } |
| 688 | 646 |
| 689 bool GetAppOutputWithExitCode(const CommandLine& cl, | 647 bool GetAppOutputWithExitCode(const CommandLine& cl, |
| 690 std::string* output, | 648 std::string* output, |
| 691 int* exit_code) { | 649 int* exit_code) { |
| 692 // Run |execve()| with the current environment and store "unlimited" data. | 650 // Run |execve()| with the current environment. |
| 693 GetAppOutputInternalResult result = GetAppOutputInternal( | 651 return GetAppOutputInternal(cl.argv(), nullptr, false, output, true, |
| 694 cl.argv(), NULL, false, output, std::numeric_limits<std::size_t>::max(), | 652 exit_code); |
| 695 true, exit_code); | |
| 696 return result == EXECUTE_SUCCESS; | |
| 697 } | 653 } |
| 698 | 654 |
| 699 #endif // !defined(OS_NACL_NONSFI) | 655 #endif // !defined(OS_NACL_NONSFI) |
| 700 | 656 |
| 701 #if defined(OS_LINUX) || defined(OS_NACL_NONSFI) | 657 #if defined(OS_LINUX) || defined(OS_NACL_NONSFI) |
| 702 namespace { | 658 namespace { |
| 703 | 659 |
| 704 bool IsRunningOnValgrind() { | 660 bool IsRunningOnValgrind() { |
| 705 return RUNNING_ON_VALGRIND; | 661 return RUNNING_ON_VALGRIND; |
| 706 } | 662 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 783 jmp_buf env; | 739 jmp_buf env; |
| 784 if (setjmp(env) == 0) { | 740 if (setjmp(env) == 0) { |
| 785 return CloneAndLongjmpInChild(flags, ptid, ctid, &env); | 741 return CloneAndLongjmpInChild(flags, ptid, ctid, &env); |
| 786 } | 742 } |
| 787 | 743 |
| 788 return 0; | 744 return 0; |
| 789 } | 745 } |
| 790 #endif // defined(OS_LINUX) || defined(OS_NACL_NONSFI) | 746 #endif // defined(OS_LINUX) || defined(OS_NACL_NONSFI) |
| 791 | 747 |
| 792 } // namespace base | 748 } // namespace base |
| OLD | NEW |