OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #define _CRT_SECURE_NO_WARNINGS | 5 #define _CRT_SECURE_NO_WARNINGS |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/debug_util.h" | |
10 #include "base/eintr_wrapper.h" | 11 #include "base/eintr_wrapper.h" |
11 #include "base/file_path.h" | 12 #include "base/file_path.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 #include "base/path_service.h" | 14 #include "base/path_service.h" |
14 #include "base/platform_thread.h" | 15 #include "base/platform_thread.h" |
15 #include "base/process_util.h" | 16 #include "base/process_util.h" |
16 #include "base/scoped_ptr.h" | 17 #include "base/scoped_ptr.h" |
17 #include "base/test/multiprocess_test.h" | 18 #include "base/test/multiprocess_test.h" |
18 #include "base/utf_string_conversions.h" | 19 #include "base/utf_string_conversions.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
20 #include "testing/multiprocess_func_list.h" | 21 #include "testing/multiprocess_func_list.h" |
21 | 22 |
22 #if defined(OS_LINUX) | 23 #if defined(OS_LINUX) |
23 #include <errno.h> | 24 #include <errno.h> |
24 #include <malloc.h> | 25 #include <malloc.h> |
25 #include <glib.h> | 26 #include <glib.h> |
26 #endif | 27 #endif |
27 #if defined(OS_POSIX) | 28 #if defined(OS_POSIX) |
28 #include <dlfcn.h> | 29 #include <dlfcn.h> |
29 #include <fcntl.h> | 30 #include <fcntl.h> |
31 #include <signal.h> | |
30 #include <sys/resource.h> | 32 #include <sys/resource.h> |
31 #include <sys/socket.h> | 33 #include <sys/socket.h> |
32 #endif | 34 #endif |
33 #if defined(OS_WIN) | 35 #if defined(OS_WIN) |
34 #include <windows.h> | 36 #include <windows.h> |
35 #endif | 37 #endif |
36 #if defined(OS_MACOSX) | 38 #if defined(OS_MACOSX) |
37 #include <malloc/malloc.h> | 39 #include <malloc/malloc.h> |
38 #include "base/process_util_unittest_mac.h" | 40 #include "base/process_util_unittest_mac.h" |
39 #endif | 41 #endif |
40 | 42 |
41 namespace { | 43 namespace { |
42 | 44 |
43 #if defined(OS_WIN) | 45 #if defined(OS_WIN) |
44 const wchar_t* const kProcessName = L"base_unittests.exe"; | 46 const wchar_t kProcessName[] = L"base_unittests.exe"; |
45 #else | 47 #else |
46 const wchar_t* const kProcessName = L"base_unittests"; | 48 const wchar_t kProcessName[] = L"base_unittests"; |
47 #endif // defined(OS_WIN) | 49 #endif // defined(OS_WIN) |
48 | 50 |
51 const char kSignalFileSlow[] = "SlowChildProcess.die"; | |
52 const char kSignalFileCrash[] = "CrashingChildProcess.die"; | |
53 const char kSignalFileKill[] = "KilledChildProcess.die"; | |
54 | |
55 #if defined(OS_WIN) | |
56 const int kExpectedStillRunningExitCode = 0x102; | |
57 #else | |
58 const int kExpectedStillRunningExitCode = 0; | |
59 #endif | |
60 | |
61 // The longest we'll wait for a process, in milliseconds. | |
62 const int kMaxWaitTimeMs = 5000; | |
Paweł Hajdan Jr.
2010/11/30 09:39:38
Please use base/test/test_timeouts.
Greg Spencer (Chromium)
2010/11/30 19:42:29
Done.
| |
63 | |
49 // Sleeps until file filename is created. | 64 // Sleeps until file filename is created. |
50 void WaitToDie(const char* filename) { | 65 void WaitToDie(const char* filename) { |
51 FILE *fp; | 66 FILE *fp; |
52 do { | 67 do { |
53 PlatformThread::Sleep(10); | 68 PlatformThread::Sleep(10); |
54 fp = fopen(filename, "r"); | 69 fp = fopen(filename, "r"); |
55 } while (!fp); | 70 } while (!fp); |
56 fclose(fp); | 71 fclose(fp); |
57 } | 72 } |
58 | 73 |
59 // Signals children they should die now. | 74 // Signals children they should die now. |
60 void SignalChildren(const char* filename) { | 75 void SignalChildren(const char* filename) { |
61 FILE *fp = fopen(filename, "w"); | 76 FILE *fp = fopen(filename, "w"); |
62 fclose(fp); | 77 fclose(fp); |
63 } | 78 } |
64 | 79 |
80 // Using a pipe to the child to wait for an event was considered, but | |
81 // there were cases in the past where pipes caused problems (other | |
82 // libraries closing the fds, child deadlocking). This is a simple | |
83 // case, so it's not worth the risk. Using wait loops is discouraged | |
84 // in most instances. | |
85 base::TerminationStatus WaitForChildTermination(base::ProcessHandle handle, | |
86 int* exit_code) { | |
87 // Now we wait until the result is something other than STILL_RUNNING. | |
88 base::TerminationStatus status = base::TERMINATION_STATUS_STILL_RUNNING; | |
89 const int kIntervalMs = 20; | |
90 int waited = 0; | |
91 do { | |
92 status = base::GetTerminationStatus(handle, exit_code); | |
93 PlatformThread::Sleep(kIntervalMs); | |
94 waited += kIntervalMs; | |
95 } while (status == base::TERMINATION_STATUS_STILL_RUNNING && | |
96 waited < kMaxWaitTimeMs); | |
97 | |
98 return status; | |
99 } | |
100 | |
65 } // namespace | 101 } // namespace |
66 | 102 |
67 class ProcessUtilTest : public base::MultiProcessTest { | 103 class ProcessUtilTest : public base::MultiProcessTest { |
68 #if defined(OS_POSIX) | 104 #if defined(OS_POSIX) |
69 public: | 105 public: |
70 // Spawn a child process that counts how many file descriptors are open. | 106 // Spawn a child process that counts how many file descriptors are open. |
71 int CountOpenFDsInChild(); | 107 int CountOpenFDsInChild(); |
72 #endif | 108 #endif |
73 }; | 109 }; |
74 | 110 |
75 MULTIPROCESS_TEST_MAIN(SimpleChildProcess) { | 111 MULTIPROCESS_TEST_MAIN(SimpleChildProcess) { |
76 return 0; | 112 return 0; |
77 } | 113 } |
78 | 114 |
79 TEST_F(ProcessUtilTest, SpawnChild) { | 115 TEST_F(ProcessUtilTest, SpawnChild) { |
80 base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false); | 116 base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false); |
81 ASSERT_NE(base::kNullProcessHandle, handle); | 117 ASSERT_NE(base::kNullProcessHandle, handle); |
82 EXPECT_TRUE(base::WaitForSingleProcess(handle, 5000)); | 118 EXPECT_TRUE(base::WaitForSingleProcess(handle, kMaxWaitTimeMs)); |
83 base::CloseProcessHandle(handle); | 119 base::CloseProcessHandle(handle); |
84 } | 120 } |
85 | 121 |
86 MULTIPROCESS_TEST_MAIN(SlowChildProcess) { | 122 MULTIPROCESS_TEST_MAIN(SlowChildProcess) { |
87 WaitToDie("SlowChildProcess.die"); | 123 WaitToDie(kSignalFileSlow); |
88 return 0; | 124 return 0; |
89 } | 125 } |
90 | 126 |
91 TEST_F(ProcessUtilTest, KillSlowChild) { | 127 TEST_F(ProcessUtilTest, KillSlowChild) { |
92 remove("SlowChildProcess.die"); | 128 remove(kSignalFileSlow); |
93 base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false); | 129 base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false); |
94 ASSERT_NE(base::kNullProcessHandle, handle); | 130 ASSERT_NE(base::kNullProcessHandle, handle); |
95 SignalChildren("SlowChildProcess.die"); | 131 SignalChildren(kSignalFileSlow); |
96 EXPECT_TRUE(base::WaitForSingleProcess(handle, 5000)); | 132 EXPECT_TRUE(base::WaitForSingleProcess(handle, kMaxWaitTimeMs)); |
97 base::CloseProcessHandle(handle); | 133 base::CloseProcessHandle(handle); |
98 remove("SlowChildProcess.die"); | 134 remove(kSignalFileSlow); |
99 } | 135 } |
100 | 136 |
101 TEST_F(ProcessUtilTest, DidProcessCrash) { | 137 TEST_F(ProcessUtilTest, GetTerminationStatusExit) { |
102 remove("SlowChildProcess.die"); | 138 remove(kSignalFileSlow); |
103 base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false); | 139 base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false); |
104 ASSERT_NE(base::kNullProcessHandle, handle); | 140 ASSERT_NE(base::kNullProcessHandle, handle); |
105 | 141 |
106 bool child_exited = true; | 142 int exit_code = 42; |
107 EXPECT_FALSE(base::DidProcessCrash(&child_exited, handle)); | 143 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, |
108 EXPECT_FALSE(child_exited); | 144 base::GetTerminationStatus(handle, &exit_code)); |
145 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); | |
109 | 146 |
110 SignalChildren("SlowChildProcess.die"); | 147 SignalChildren(kSignalFileSlow); |
111 EXPECT_TRUE(base::WaitForSingleProcess(handle, 5000)); | 148 exit_code = 42; |
149 base::TerminationStatus status = | |
150 WaitForChildTermination(handle, &exit_code); | |
Paweł Hajdan Jr.
2010/11/30 09:39:38
Why not WaitForSingleProcess?
Greg Spencer (Chromium)
2010/11/30 19:42:29
Because on Linux, WaitForSingleProcess uses waitpi
Paweł Hajdan Jr.
2010/12/01 08:40:46
I suspected something like that. However, the prev
| |
151 EXPECT_EQ(base::TERMINATION_STATUS_NORMAL_TERMINATION, status); | |
152 EXPECT_EQ(0, exit_code); | |
153 base::CloseProcessHandle(handle); | |
154 remove(kSignalFileSlow); | |
155 } | |
112 | 156 |
113 EXPECT_FALSE(base::DidProcessCrash(&child_exited, handle)); | 157 MULTIPROCESS_TEST_MAIN(CrashingChildProcess) { |
158 WaitToDie(kSignalFileCrash); | |
159 #if defined(OS_MACOSX) | |
160 // Have to reset the exception ports on mac so we get a crash. | |
161 base::RestoreDefaultExceptionHandler(); | |
162 // We disable crash dumps because we don't really need one if we are | |
163 // *trying* to cause a crash. | |
164 DebugUtil::DisableOSCrashDumps(); | |
165 // Mac gets a SIGBUS instead of SIGSEGV on x86 (but not x86_64), so | |
166 // we have to disable handling for both. | |
167 ::signal(SIGBUS, SIG_DFL); | |
168 #endif | |
169 #if defined(OS_POSIX) | |
170 // Have to disable to signal handler for segv so we can get a crash | |
171 // instead of an abnormal termination through the crash dump handler. | |
172 ::signal(SIGSEGV, SIG_DFL); | |
173 #endif | |
174 // Make this process have a segmentation fault. | |
175 int* oops = NULL; | |
176 *oops = 0xDEAD; | |
177 return 1; | |
178 } | |
179 | |
180 TEST_F(ProcessUtilTest, GetTerminationStatusCrash) { | |
181 remove(kSignalFileCrash); | |
182 base::ProcessHandle handle = this->SpawnChild("CrashingChildProcess", | |
183 false); | |
184 ASSERT_NE(base::kNullProcessHandle, handle); | |
185 | |
186 int exit_code = 42; | |
187 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, | |
188 base::GetTerminationStatus(handle, &exit_code)); | |
189 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); | |
190 | |
191 SignalChildren(kSignalFileCrash); | |
192 exit_code = 42; | |
193 base::TerminationStatus status = | |
194 WaitForChildTermination(handle, &exit_code); | |
Paweł Hajdan Jr.
2010/11/30 09:39:38
Why not WaitForSingleProcess?
Greg Spencer (Chromium)
2010/11/30 19:42:29
See above.
| |
195 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_CRASHED, status); | |
196 | |
197 #if defined(OS_WIN) | |
198 EXPECT_EQ(0xc0000005, exit_code); | |
199 #elif defined(OS_POSIX) | |
200 int signaled = WIFSIGNALED(exit_code); | |
201 EXPECT_NE(0, signaled); | |
202 int signal = WTERMSIG(exit_code); | |
203 #if defined(OS_MACOSX) | |
204 // Mac gets a SIGBUS instead of SIGSEGV on x86 (but not x86_64), so | |
205 // we have to expect either one. | |
206 EXPECT_TRUE(signal == SIGBUS || signal == SIGSEGV); | |
207 #else | |
208 EXPECT_EQ(SIGSEGV, signal); | |
209 #endif | |
210 #endif | |
114 base::CloseProcessHandle(handle); | 211 base::CloseProcessHandle(handle); |
115 remove("SlowChildProcess.die"); | 212 |
213 // Reset signal handlers back to "normal". | |
214 base::EnableInProcessStackDumping(); | |
215 remove(kSignalFileCrash); | |
216 } | |
217 | |
218 MULTIPROCESS_TEST_MAIN(KilledChildProcess) { | |
219 WaitToDie(kSignalFileKill); | |
220 #if defined(OS_WIN) | |
221 // Kill ourselves. | |
222 HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ::GetCurrentProcessId()); | |
223 ::TerminateProcess(handle, base::PROCESS_END_PROCESS_WAS_KILLED); | |
224 #elif defined(OS_POSIX) | |
225 // Send a SIGKILL to this process, just like the OOM killer would. | |
226 ::kill(getpid(), SIGKILL); | |
227 #endif | |
228 return 1; | |
229 } | |
230 | |
231 TEST_F(ProcessUtilTest, GetTerminationStatusKill) { | |
232 remove(kSignalFileKill); | |
233 base::ProcessHandle handle = this->SpawnChild("KilledChildProcess", | |
234 false); | |
235 ASSERT_NE(base::kNullProcessHandle, handle); | |
236 | |
237 int exit_code = 42; | |
238 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, | |
239 base::GetTerminationStatus(handle, &exit_code)); | |
240 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); | |
241 | |
242 SignalChildren(kSignalFileKill); | |
243 exit_code = 42; | |
244 base::TerminationStatus status = | |
245 WaitForChildTermination(handle, &exit_code); | |
Paweł Hajdan Jr.
2010/11/30 09:39:38
Why not WaitForSingleProcess?
Greg Spencer (Chromium)
2010/11/30 19:42:29
See above.
| |
246 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_WAS_KILLED, status); | |
247 #if defined(OS_WIN) | |
248 EXPECT_EQ(base::PROCESS_END_PROCESS_WAS_KILLED, exit_code); | |
249 #elif defined(OS_POSIX) | |
250 int signaled = WIFSIGNALED(exit_code); | |
251 EXPECT_NE(0, signaled); | |
252 int signal = WTERMSIG(exit_code); | |
253 EXPECT_EQ(SIGKILL, signal); | |
254 #endif | |
255 base::CloseProcessHandle(handle); | |
256 remove(kSignalFileKill); | |
116 } | 257 } |
117 | 258 |
118 // Ensure that the priority of a process is restored correctly after | 259 // Ensure that the priority of a process is restored correctly after |
119 // backgrounding and restoring. | 260 // backgrounding and restoring. |
120 // Note: a platform may not be willing or able to lower the priority of | 261 // Note: a platform may not be willing or able to lower the priority of |
121 // a process. The calls to SetProcessBackground should be noops then. | 262 // a process. The calls to SetProcessBackground should be noops then. |
122 TEST_F(ProcessUtilTest, SetProcessBackgrounded) { | 263 TEST_F(ProcessUtilTest, SetProcessBackgrounded) { |
123 base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false); | 264 base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false); |
124 base::Process process(handle); | 265 base::Process process(handle); |
125 int old_priority = process.GetPriority(); | 266 int old_priority = process.GetPriority(); |
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 ASSERT_DEATH({ | 922 ASSERT_DEATH({ |
782 SetUpInDeathAssert(); | 923 SetUpInDeathAssert(); |
783 while ((value_ = base::AllocatePsychoticallyBigObjCObject())) {} | 924 while ((value_ = base::AllocatePsychoticallyBigObjCObject())) {} |
784 }, ""); | 925 }, ""); |
785 } | 926 } |
786 | 927 |
787 #endif // !ARCH_CPU_64_BITS | 928 #endif // !ARCH_CPU_64_BITS |
788 #endif // OS_MACOSX | 929 #endif // OS_MACOSX |
789 | 930 |
790 #endif // !defined(OS_WIN) | 931 #endif // !defined(OS_WIN) |
OLD | NEW |