OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/test/test_launcher.h" | 5 #include "base/test/test_launcher.h" |
6 | 6 |
| 7 #if defined(OS_POSIX) |
| 8 #include <fcntl.h> |
| 9 #endif |
| 10 |
7 #include "base/at_exit.h" | 11 #include "base/at_exit.h" |
8 #include "base/bind.h" | 12 #include "base/bind.h" |
9 #include "base/command_line.h" | 13 #include "base/command_line.h" |
10 #include "base/environment.h" | 14 #include "base/environment.h" |
11 #include "base/file_util.h" | 15 #include "base/file_util.h" |
12 #include "base/files/file_path.h" | 16 #include "base/files/file_path.h" |
13 #include "base/format_macros.h" | 17 #include "base/format_macros.h" |
| 18 #include "base/lazy_instance.h" |
14 #include "base/logging.h" | 19 #include "base/logging.h" |
15 #include "base/memory/scoped_ptr.h" | 20 #include "base/memory/scoped_ptr.h" |
16 #include "base/message_loop/message_loop.h" | 21 #include "base/message_loop/message_loop.h" |
17 #include "base/process/kill.h" | 22 #include "base/process/kill.h" |
18 #include "base/process/launch.h" | 23 #include "base/process/launch.h" |
19 #include "base/strings/string_number_conversions.h" | 24 #include "base/strings/string_number_conversions.h" |
20 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
21 #include "base/strings/utf_string_conversions.h" | 26 #include "base/strings/utf_string_conversions.h" |
22 #include "base/test/test_timeouts.h" | 27 #include "base/test/test_timeouts.h" |
23 #include "base/threading/thread_checker.h" | 28 #include "base/threading/thread_checker.h" |
(...skipping 13 matching lines...) Expand all Loading... |
37 const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; | 42 const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS"; |
38 // The environment variable name for the test shard index. | 43 // The environment variable name for the test shard index. |
39 const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; | 44 const char kTestShardIndex[] = "GTEST_SHARD_INDEX"; |
40 | 45 |
41 // The default output file for XML output. | 46 // The default output file for XML output. |
42 const FilePath::CharType kDefaultOutputFile[] = FILE_PATH_LITERAL( | 47 const FilePath::CharType kDefaultOutputFile[] = FILE_PATH_LITERAL( |
43 "test_detail.xml"); | 48 "test_detail.xml"); |
44 | 49 |
45 namespace { | 50 namespace { |
46 | 51 |
| 52 // Set of live launch test processes with corresponding lock (it is allowed |
| 53 // for callers to launch processes on different threads). |
| 54 LazyInstance<std::set<ProcessHandle> > g_live_process_handles |
| 55 = LAZY_INSTANCE_INITIALIZER; |
| 56 LazyInstance<Lock> g_live_process_handles_lock = LAZY_INSTANCE_INITIALIZER; |
| 57 |
| 58 #if defined(OS_POSIX) |
| 59 // Self-pipe that makes it possible to do complex shutdown handling |
| 60 // outside of the signal handler. |
| 61 int g_shutdown_pipe[2] = { -1, -1 }; |
| 62 |
| 63 void ShutdownPipeSignalHandler(int signal) { |
| 64 HANDLE_EINTR(write(g_shutdown_pipe[1], "q", 1)); |
| 65 } |
| 66 |
| 67 // I/O watcher for the reading end of the self-pipe above. |
| 68 // Terminates any launched child processes and exits the process. |
| 69 class SignalFDWatcher : public MessageLoopForIO::Watcher { |
| 70 public: |
| 71 SignalFDWatcher() { |
| 72 } |
| 73 |
| 74 virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE { |
| 75 fprintf(stdout, "\nCaught signal. Killing spawned test processes...\n"); |
| 76 fflush(stdout); |
| 77 |
| 78 // Keep the lock until exiting the process to prevent further processes |
| 79 // from being spawned. |
| 80 AutoLock lock(g_live_process_handles_lock.Get()); |
| 81 |
| 82 fprintf(stdout, |
| 83 "Sending SIGTERM to %" PRIuS " child processes... ", |
| 84 g_live_process_handles.Get().size()); |
| 85 fflush(stdout); |
| 86 |
| 87 for (std::set<ProcessHandle>::iterator i = |
| 88 g_live_process_handles.Get().begin(); |
| 89 i != g_live_process_handles.Get().end(); |
| 90 ++i) { |
| 91 kill((-1) * (*i), SIGTERM); // Send the signal to entire process group. |
| 92 } |
| 93 |
| 94 fprintf(stdout, |
| 95 "done.\nGiving processes a chance to terminate cleanly... "); |
| 96 fflush(stdout); |
| 97 |
| 98 PlatformThread::Sleep(TimeDelta::FromMilliseconds(500)); |
| 99 |
| 100 fprintf(stdout, "done.\n"); |
| 101 fflush(stdout); |
| 102 |
| 103 fprintf(stdout, |
| 104 "Sending SIGKILL to %" PRIuS " child processes... ", |
| 105 g_live_process_handles.Get().size()); |
| 106 fflush(stdout); |
| 107 |
| 108 for (std::set<ProcessHandle>::iterator i = |
| 109 g_live_process_handles.Get().begin(); |
| 110 i != g_live_process_handles.Get().end(); |
| 111 ++i) { |
| 112 kill((-1) * (*i), SIGKILL); // Send the signal to entire process group. |
| 113 } |
| 114 |
| 115 fprintf(stdout, "done.\n"); |
| 116 fflush(stdout); |
| 117 |
| 118 // The signal would normally kill the process, so exit now. |
| 119 exit(1); |
| 120 } |
| 121 |
| 122 virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE { |
| 123 NOTREACHED(); |
| 124 } |
| 125 |
| 126 private: |
| 127 DISALLOW_COPY_AND_ASSIGN(SignalFDWatcher); |
| 128 }; |
| 129 #endif // defined(OS_POSIX) |
| 130 |
47 // Parses the environment variable var as an Int32. If it is unset, returns | 131 // Parses the environment variable var as an Int32. If it is unset, returns |
48 // default_val. If it is set, unsets it then converts it to Int32 before | 132 // default_val. If it is set, unsets it then converts it to Int32 before |
49 // returning it. If unsetting or converting to an Int32 fails, print an | 133 // returning it. If unsetting or converting to an Int32 fails, print an |
50 // error and exit with failure. | 134 // error and exit with failure. |
51 int32 Int32FromEnvOrDie(const char* const var, int32 default_val) { | 135 int32 Int32FromEnvOrDie(const char* const var, int32 default_val) { |
52 scoped_ptr<Environment> env(Environment::Create()); | 136 scoped_ptr<Environment> env(Environment::Create()); |
53 std::string str_val; | 137 std::string str_val; |
54 int32 result; | 138 int32 result; |
55 if (!env->GetVar(var, &str_val)) | 139 if (!env->GetVar(var, &str_val)) |
56 return default_val; | 140 return default_val; |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 int LaunchChildTestProcessWithOptions(const CommandLine& command_line, | 618 int LaunchChildTestProcessWithOptions(const CommandLine& command_line, |
535 const LaunchOptions& options, | 619 const LaunchOptions& options, |
536 base::TimeDelta timeout, | 620 base::TimeDelta timeout, |
537 bool* was_timeout) { | 621 bool* was_timeout) { |
538 #if defined(OS_POSIX) | 622 #if defined(OS_POSIX) |
539 // Make sure an option we rely on is present - see LaunchChildGTestProcess. | 623 // Make sure an option we rely on is present - see LaunchChildGTestProcess. |
540 DCHECK(options.new_process_group); | 624 DCHECK(options.new_process_group); |
541 #endif | 625 #endif |
542 | 626 |
543 base::ProcessHandle process_handle; | 627 base::ProcessHandle process_handle; |
544 if (!base::LaunchProcess(command_line, options, &process_handle)) | 628 |
545 return -1; | 629 { |
| 630 // Note how we grab the lock before the process possibly gets created. |
| 631 // This ensures that when the lock is held, ALL the processes are registered |
| 632 // in the set. |
| 633 AutoLock lock(g_live_process_handles_lock.Get()); |
| 634 |
| 635 if (!base::LaunchProcess(command_line, options, &process_handle)) |
| 636 return -1; |
| 637 |
| 638 g_live_process_handles.Get().insert(process_handle); |
| 639 } |
546 | 640 |
547 int exit_code = 0; | 641 int exit_code = 0; |
548 if (!base::WaitForExitCodeWithTimeout(process_handle, | 642 if (!base::WaitForExitCodeWithTimeout(process_handle, |
549 &exit_code, | 643 &exit_code, |
550 timeout)) { | 644 timeout)) { |
551 *was_timeout = true; | 645 *was_timeout = true; |
552 exit_code = -1; // Set a non-zero exit code to signal a failure. | 646 exit_code = -1; // Set a non-zero exit code to signal a failure. |
553 | 647 |
554 // Ensure that the process terminates. | 648 // Ensure that the process terminates. |
555 base::KillProcess(process_handle, -1, true); | 649 base::KillProcess(process_handle, -1, true); |
556 } | 650 } |
557 | 651 |
| 652 { |
| 653 // Note how we grab the log before issuing a possibly broad process kill. |
| 654 // Other code parts that grab the log kill processes, so avoid trying |
| 655 // to do that twice and trigger all kinds of log messages. |
| 656 AutoLock lock(g_live_process_handles_lock.Get()); |
| 657 |
558 #if defined(OS_POSIX) | 658 #if defined(OS_POSIX) |
559 if (exit_code != 0) { | 659 if (exit_code != 0) { |
560 // On POSIX, in case the test does not exit cleanly, either due to a crash | 660 // On POSIX, in case the test does not exit cleanly, either due to a crash |
561 // or due to it timing out, we need to clean up any child processes that | 661 // or due to it timing out, we need to clean up any child processes that |
562 // it might have created. On Windows, child processes are automatically | 662 // it might have created. On Windows, child processes are automatically |
563 // cleaned up using JobObjects. | 663 // cleaned up using JobObjects. |
564 base::KillProcessGroup(process_handle); | 664 base::KillProcessGroup(process_handle); |
| 665 } |
| 666 #endif |
| 667 |
| 668 g_live_process_handles.Get().erase(process_handle); |
565 } | 669 } |
566 #endif | |
567 | 670 |
568 base::CloseProcessHandle(process_handle); | 671 base::CloseProcessHandle(process_handle); |
569 | 672 |
570 return exit_code; | 673 return exit_code; |
571 } | 674 } |
572 | 675 |
573 int LaunchTests(TestLauncherDelegate* launcher_delegate, | 676 int LaunchTests(TestLauncherDelegate* launcher_delegate, |
574 int argc, | 677 int argc, |
575 char** argv) { | 678 char** argv) { |
576 const CommandLine* command_line = CommandLine::ForCurrentProcess(); | 679 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
577 | 680 |
578 | 681 |
579 int32 total_shards; | 682 int32 total_shards; |
580 int32 shard_index; | 683 int32 shard_index; |
581 InitSharding(&total_shards, &shard_index); | 684 InitSharding(&total_shards, &shard_index); |
582 | 685 |
583 int cycles = 1; | 686 int cycles = 1; |
584 if (command_line->HasSwitch(kGTestRepeatFlag)) | 687 if (command_line->HasSwitch(kGTestRepeatFlag)) |
585 StringToInt(command_line->GetSwitchValueASCII(kGTestRepeatFlag), &cycles); | 688 StringToInt(command_line->GetSwitchValueASCII(kGTestRepeatFlag), &cycles); |
586 | 689 |
587 int exit_code = 0; | 690 int exit_code = 0; |
588 | 691 |
| 692 #if defined(OS_POSIX) |
| 693 CHECK_EQ(0, pipe(g_shutdown_pipe)); |
| 694 |
| 695 struct sigaction action; |
| 696 memset(&action, 0, sizeof(action)); |
| 697 sigemptyset(&action.sa_mask); |
| 698 action.sa_handler = &ShutdownPipeSignalHandler; |
| 699 |
| 700 CHECK_EQ(0, sigaction(SIGINT, &action, NULL)); |
| 701 CHECK_EQ(0, sigaction(SIGQUIT, &action, NULL)); |
| 702 CHECK_EQ(0, sigaction(SIGTERM, &action, NULL)); |
| 703 |
| 704 MessageLoopForIO::FileDescriptorWatcher controller; |
| 705 SignalFDWatcher watcher; |
| 706 |
| 707 CHECK(MessageLoopForIO::current()->WatchFileDescriptor( |
| 708 g_shutdown_pipe[0], |
| 709 true, |
| 710 MessageLoopForIO::WATCH_READ, |
| 711 &controller, |
| 712 &watcher)); |
| 713 #endif // defined(OS_POSIX) |
| 714 |
589 MessageLoop::current()->PostTask( | 715 MessageLoop::current()->PostTask( |
590 FROM_HERE, | 716 FROM_HERE, |
591 Bind(&RunTestIteration, | 717 Bind(&RunTestIteration, |
592 launcher_delegate, | 718 launcher_delegate, |
593 total_shards, | 719 total_shards, |
594 shard_index, | 720 shard_index, |
595 cycles, | 721 cycles, |
596 &exit_code, | 722 &exit_code, |
597 true)); | 723 true)); |
598 | 724 |
599 MessageLoop::current()->Run(); | 725 MessageLoop::current()->Run(); |
600 | 726 |
601 return exit_code; | 727 return exit_code; |
602 } | 728 } |
603 | 729 |
604 } // namespace base | 730 } // namespace base |
OLD | NEW |