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/launcher/test_launcher.h" | 5 #include "base/test/launcher/test_launcher.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "base/at_exit.h" | 9 #include "base/at_exit.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
90 // Avoids flooding the logs with amount of output that gums up | 90 // Avoids flooding the logs with amount of output that gums up |
91 // the infrastructure. | 91 // the infrastructure. |
92 const size_t kOutputSnippetLinesLimit = 5000; | 92 const size_t kOutputSnippetLinesLimit = 5000; |
93 | 93 |
94 // Limit of output snippet size. Exceeding this limit | 94 // Limit of output snippet size. Exceeding this limit |
95 // results in truncating the output and failing the test. | 95 // results in truncating the output and failing the test. |
96 const size_t kOutputSnippetBytesLimit = 300 * 1024; | 96 const size_t kOutputSnippetBytesLimit = 300 * 1024; |
97 | 97 |
98 // Set of live launch test processes with corresponding lock (it is allowed | 98 // Set of live launch test processes with corresponding lock (it is allowed |
99 // for callers to launch processes on different threads). | 99 // for callers to launch processes on different threads). |
100 LazyInstance<std::map<ProcessHandle, CommandLine>>::DestructorAtExit | 100 Lock* GetLiveProcessesLock() { |
101 g_live_processes = LAZY_INSTANCE_INITIALIZER; | 101 static auto* lock = new Lock; |
102 LazyInstance<Lock>::DestructorAtExit g_live_processes_lock = | 102 return lock; |
103 LAZY_INSTANCE_INITIALIZER; | 103 } |
| 104 |
| 105 std::map<ProcessHandle, CommandLine>* GetLiveProcesses() { |
| 106 static auto* map = new std::map<ProcessHandle, CommandLine>; |
| 107 return map; |
| 108 } |
104 | 109 |
105 // Performance trace generator. | 110 // Performance trace generator. |
106 LazyInstance<TestLauncherTracer>::DestructorAtExit g_tracer = | 111 TestLauncherTracer* GetTestLauncherTracer() { |
107 LAZY_INSTANCE_INITIALIZER; | 112 static auto* tracer = new TestLauncherTracer; |
| 113 return tracer; |
| 114 } |
108 | 115 |
109 #if defined(OS_POSIX) | 116 #if defined(OS_POSIX) |
110 // Self-pipe that makes it possible to do complex shutdown handling | 117 // Self-pipe that makes it possible to do complex shutdown handling |
111 // outside of the signal handler. | 118 // outside of the signal handler. |
112 int g_shutdown_pipe[2] = { -1, -1 }; | 119 int g_shutdown_pipe[2] = { -1, -1 }; |
113 | 120 |
114 void ShutdownPipeSignalHandler(int signal) { | 121 void ShutdownPipeSignalHandler(int signal) { |
115 HANDLE_EINTR(write(g_shutdown_pipe[1], "q", 1)); | 122 HANDLE_EINTR(write(g_shutdown_pipe[1], "q", 1)); |
116 } | 123 } |
117 | 124 |
118 void KillSpawnedTestProcesses() { | 125 void KillSpawnedTestProcesses() { |
119 // Keep the lock until exiting the process to prevent further processes | 126 // Keep the lock until exiting the process to prevent further processes |
120 // from being spawned. | 127 // from being spawned. |
121 AutoLock lock(g_live_processes_lock.Get()); | 128 AutoLock lock(*GetLiveProcessesLock()); |
122 | 129 |
123 fprintf(stdout, | 130 fprintf(stdout, "Sending SIGTERM to %" PRIuS " child processes... ", |
124 "Sending SIGTERM to %" PRIuS " child processes... ", | 131 GetLiveProcesses()->size()); |
125 g_live_processes.Get().size()); | |
126 fflush(stdout); | 132 fflush(stdout); |
127 | 133 |
128 for (std::map<ProcessHandle, CommandLine>::iterator i = | 134 for (const auto& pair : *GetLiveProcesses()) { |
129 g_live_processes.Get().begin(); | |
130 i != g_live_processes.Get().end(); | |
131 ++i) { | |
132 // Send the signal to entire process group. | 135 // Send the signal to entire process group. |
133 kill((-1) * (i->first), SIGTERM); | 136 kill((-1) * (pair.first), SIGTERM); |
134 } | 137 } |
135 | 138 |
136 fprintf(stdout, | 139 fprintf(stdout, |
137 "done.\nGiving processes a chance to terminate cleanly... "); | 140 "done.\nGiving processes a chance to terminate cleanly... "); |
138 fflush(stdout); | 141 fflush(stdout); |
139 | 142 |
140 PlatformThread::Sleep(TimeDelta::FromMilliseconds(500)); | 143 PlatformThread::Sleep(TimeDelta::FromMilliseconds(500)); |
141 | 144 |
142 fprintf(stdout, "done.\n"); | 145 fprintf(stdout, "done.\n"); |
143 fflush(stdout); | 146 fflush(stdout); |
144 | 147 |
145 fprintf(stdout, | 148 fprintf(stdout, "Sending SIGKILL to %" PRIuS " child processes... ", |
146 "Sending SIGKILL to %" PRIuS " child processes... ", | 149 GetLiveProcesses()->size()); |
147 g_live_processes.Get().size()); | |
148 fflush(stdout); | 150 fflush(stdout); |
149 | 151 |
150 for (std::map<ProcessHandle, CommandLine>::iterator i = | 152 for (const auto& pair : *GetLiveProcesses()) { |
151 g_live_processes.Get().begin(); | |
152 i != g_live_processes.Get().end(); | |
153 ++i) { | |
154 // Send the signal to entire process group. | 153 // Send the signal to entire process group. |
155 kill((-1) * (i->first), SIGKILL); | 154 kill((-1) * (pair.first), SIGKILL); |
156 } | 155 } |
157 | 156 |
158 fprintf(stdout, "done.\n"); | 157 fprintf(stdout, "done.\n"); |
159 fflush(stdout); | 158 fflush(stdout); |
160 } | 159 } |
161 | 160 |
162 // I/O watcher for the reading end of the self-pipe above. | 161 // I/O watcher for the reading end of the self-pipe above. |
163 // Terminates any launched child processes and exits the process. | 162 // Terminates any launched child processes and exits the process. |
164 void OnShutdownPipeReadable() { | 163 void OnShutdownPipeReadable() { |
165 fprintf(stdout, "\nCaught signal. Killing spawned test processes...\n"); | 164 fprintf(stdout, "\nCaught signal. Killing spawned test processes...\n"); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 // new child will be privileged and trusted. | 301 // new child will be privileged and trusted. |
303 new_options.allow_new_privs = true; | 302 new_options.allow_new_privs = true; |
304 #endif | 303 #endif |
305 | 304 |
306 Process process; | 305 Process process; |
307 | 306 |
308 { | 307 { |
309 // Note how we grab the lock before the process possibly gets created. | 308 // Note how we grab the lock before the process possibly gets created. |
310 // This ensures that when the lock is held, ALL the processes are registered | 309 // This ensures that when the lock is held, ALL the processes are registered |
311 // in the set. | 310 // in the set. |
312 AutoLock lock(g_live_processes_lock.Get()); | 311 AutoLock lock(*GetLiveProcessesLock()); |
313 | 312 |
314 #if defined(OS_WIN) | 313 #if defined(OS_WIN) |
315 // Allow the handle used to capture stdio and stdout to be inherited by the | 314 // Allow the handle used to capture stdio and stdout to be inherited by the |
316 // child. Note that this is done under g_live_processes_lock to ensure that | 315 // child. Note that this is done under GetLiveProcessesLock() to ensure that |
317 // only the desired child receives the handle. | 316 // only the desired child receives the handle. |
318 if (new_options.stdout_handle) { | 317 if (new_options.stdout_handle) { |
319 ::SetHandleInformation(new_options.stdout_handle, HANDLE_FLAG_INHERIT, | 318 ::SetHandleInformation(new_options.stdout_handle, HANDLE_FLAG_INHERIT, |
320 HANDLE_FLAG_INHERIT); | 319 HANDLE_FLAG_INHERIT); |
321 } | 320 } |
322 #endif | 321 #endif |
323 | 322 |
324 process = LaunchProcess(command_line, new_options); | 323 process = LaunchProcess(command_line, new_options); |
325 | 324 |
326 #if defined(OS_WIN) | 325 #if defined(OS_WIN) |
327 // Revoke inheritance so that the handle isn't leaked into other children. | 326 // Revoke inheritance so that the handle isn't leaked into other children. |
328 // Note that this is done under g_live_processes_lock to ensure that only | 327 // Note that this is done under GetLiveProcessesLock() to ensure that only |
329 // the desired child receives the handle. | 328 // the desired child receives the handle. |
330 if (new_options.stdout_handle) | 329 if (new_options.stdout_handle) |
331 ::SetHandleInformation(new_options.stdout_handle, HANDLE_FLAG_INHERIT, 0); | 330 ::SetHandleInformation(new_options.stdout_handle, HANDLE_FLAG_INHERIT, 0); |
332 #endif | 331 #endif |
333 | 332 |
334 if (!process.IsValid()) | 333 if (!process.IsValid()) |
335 return -1; | 334 return -1; |
336 | 335 |
337 // TODO(rvargas) crbug.com/417532: Don't store process handles. | 336 // TODO(rvargas) crbug.com/417532: Don't store process handles. |
338 g_live_processes.Get().insert(std::make_pair(process.Handle(), | 337 GetLiveProcesses()->insert(std::make_pair(process.Handle(), command_line)); |
339 command_line)); | |
340 } | 338 } |
341 | 339 |
342 if (!launched_callback.is_null()) | 340 if (!launched_callback.is_null()) |
343 launched_callback.Run(process.Handle(), process.Pid()); | 341 launched_callback.Run(process.Handle(), process.Pid()); |
344 | 342 |
345 int exit_code = 0; | 343 int exit_code = 0; |
346 if (!process.WaitForExitWithTimeout(timeout, &exit_code)) { | 344 if (!process.WaitForExitWithTimeout(timeout, &exit_code)) { |
347 *was_timeout = true; | 345 *was_timeout = true; |
348 exit_code = -1; // Set a non-zero exit code to signal a failure. | 346 exit_code = -1; // Set a non-zero exit code to signal a failure. |
349 | 347 |
350 // Ensure that the process terminates. | 348 // Ensure that the process terminates. |
351 process.Terminate(-1, true); | 349 process.Terminate(-1, true); |
352 } | 350 } |
353 | 351 |
354 { | 352 { |
355 // Note how we grab the log before issuing a possibly broad process kill. | 353 // Note how we grab the log before issuing a possibly broad process kill. |
356 // Other code parts that grab the log kill processes, so avoid trying | 354 // Other code parts that grab the log kill processes, so avoid trying |
357 // to do that twice and trigger all kinds of log messages. | 355 // to do that twice and trigger all kinds of log messages. |
358 AutoLock lock(g_live_processes_lock.Get()); | 356 AutoLock lock(*GetLiveProcessesLock()); |
359 | 357 |
360 #if defined(OS_POSIX) | 358 #if defined(OS_POSIX) |
361 if (exit_code != 0) { | 359 if (exit_code != 0) { |
362 // On POSIX, in case the test does not exit cleanly, either due to a crash | 360 // On POSIX, in case the test does not exit cleanly, either due to a crash |
363 // or due to it timing out, we need to clean up any child processes that | 361 // or due to it timing out, we need to clean up any child processes that |
364 // it might have created. On Windows, child processes are automatically | 362 // it might have created. On Windows, child processes are automatically |
365 // cleaned up using JobObjects. | 363 // cleaned up using JobObjects. |
366 KillProcessGroup(process.Handle()); | 364 KillProcessGroup(process.Handle()); |
367 } | 365 } |
368 #endif | 366 #endif |
369 | 367 |
370 g_live_processes.Get().erase(process.Handle()); | 368 GetLiveProcesses()->erase(process.Handle()); |
371 } | 369 } |
372 | 370 |
373 g_tracer.Get().RecordProcessExecution(start_time, | 371 GetTestLauncherTracer()->RecordProcessExecution( |
374 TimeTicks::Now() - start_time); | 372 start_time, TimeTicks::Now() - start_time); |
375 | 373 |
376 return exit_code; | 374 return exit_code; |
377 } | 375 } |
378 | 376 |
379 void RunCallback(const TestLauncher::GTestProcessCompletedCallback& callback, | 377 void RunCallback(const TestLauncher::GTestProcessCompletedCallback& callback, |
380 int exit_code, | 378 int exit_code, |
381 const TimeDelta& elapsed_time, | 379 const TimeDelta& elapsed_time, |
382 bool was_timeout, | 380 bool was_timeout, |
383 const std::string& output) { | 381 const std::string& output) { |
384 callback.Run(exit_code, elapsed_time, was_timeout, output); | 382 callback.Run(exit_code, elapsed_time, was_timeout, output); |
(...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1107 if (command_line->HasSwitch(switches::kTestLauncherSummaryOutput)) { | 1105 if (command_line->HasSwitch(switches::kTestLauncherSummaryOutput)) { |
1108 FilePath summary_path(command_line->GetSwitchValuePath( | 1106 FilePath summary_path(command_line->GetSwitchValuePath( |
1109 switches::kTestLauncherSummaryOutput)); | 1107 switches::kTestLauncherSummaryOutput)); |
1110 if (!results_tracker_.SaveSummaryAsJSON(summary_path, additional_tags)) { | 1108 if (!results_tracker_.SaveSummaryAsJSON(summary_path, additional_tags)) { |
1111 LOG(ERROR) << "Failed to save test launcher output summary."; | 1109 LOG(ERROR) << "Failed to save test launcher output summary."; |
1112 } | 1110 } |
1113 } | 1111 } |
1114 if (command_line->HasSwitch(switches::kTestLauncherTrace)) { | 1112 if (command_line->HasSwitch(switches::kTestLauncherTrace)) { |
1115 FilePath trace_path( | 1113 FilePath trace_path( |
1116 command_line->GetSwitchValuePath(switches::kTestLauncherTrace)); | 1114 command_line->GetSwitchValuePath(switches::kTestLauncherTrace)); |
1117 if (!g_tracer.Get().Dump(trace_path)) { | 1115 if (!GetTestLauncherTracer()->Dump(trace_path)) { |
1118 LOG(ERROR) << "Failed to save test launcher trace."; | 1116 LOG(ERROR) << "Failed to save test launcher trace."; |
1119 } | 1117 } |
1120 } | 1118 } |
1121 } | 1119 } |
1122 | 1120 |
1123 void TestLauncher::OnLaunchTestProcessFinished( | 1121 void TestLauncher::OnLaunchTestProcessFinished( |
1124 const GTestProcessCompletedCallback& callback, | 1122 const GTestProcessCompletedCallback& callback, |
1125 int exit_code, | 1123 int exit_code, |
1126 const TimeDelta& elapsed_time, | 1124 const TimeDelta& elapsed_time, |
1127 bool was_timeout, | 1125 bool was_timeout, |
(...skipping 24 matching lines...) Expand all Loading... |
1152 results_tracker_.PrintSummaryOfCurrentIteration(); | 1150 results_tracker_.PrintSummaryOfCurrentIteration(); |
1153 | 1151 |
1154 // Kick off the next iteration. | 1152 // Kick off the next iteration. |
1155 ThreadTaskRunnerHandle::Get()->PostTask( | 1153 ThreadTaskRunnerHandle::Get()->PostTask( |
1156 FROM_HERE, Bind(&TestLauncher::RunTestIteration, Unretained(this))); | 1154 FROM_HERE, Bind(&TestLauncher::RunTestIteration, Unretained(this))); |
1157 } | 1155 } |
1158 | 1156 |
1159 void TestLauncher::OnOutputTimeout() { | 1157 void TestLauncher::OnOutputTimeout() { |
1160 DCHECK(thread_checker_.CalledOnValidThread()); | 1158 DCHECK(thread_checker_.CalledOnValidThread()); |
1161 | 1159 |
1162 AutoLock lock(g_live_processes_lock.Get()); | 1160 AutoLock lock(*GetLiveProcessesLock()); |
1163 | 1161 |
1164 fprintf(stdout, "Still waiting for the following processes to finish:\n"); | 1162 fprintf(stdout, "Still waiting for the following processes to finish:\n"); |
1165 | 1163 |
1166 for (std::map<ProcessHandle, CommandLine>::iterator i = | 1164 for (const auto& pair : *GetLiveProcesses()) { |
1167 g_live_processes.Get().begin(); | |
1168 i != g_live_processes.Get().end(); | |
1169 ++i) { | |
1170 #if defined(OS_WIN) | 1165 #if defined(OS_WIN) |
1171 fwprintf(stdout, L"\t%s\n", i->second.GetCommandLineString().c_str()); | 1166 fwprintf(stdout, L"\t%s\n", pair.second.GetCommandLineString().c_str()); |
1172 #else | 1167 #else |
1173 fprintf(stdout, "\t%s\n", i->second.GetCommandLineString().c_str()); | 1168 fprintf(stdout, "\t%s\n", pair.second.GetCommandLineString().c_str()); |
1174 #endif | 1169 #endif |
1175 } | 1170 } |
1176 | 1171 |
1177 fflush(stdout); | 1172 fflush(stdout); |
1178 | 1173 |
1179 // Arm the timer again - otherwise it would fire only once. | 1174 // Arm the timer again - otherwise it would fire only once. |
1180 watchdog_timer_.Reset(); | 1175 watchdog_timer_.Reset(); |
1181 } | 1176 } |
1182 | 1177 |
1183 scoped_refptr<TaskRunner> TestLauncher::GetTaskRunner() { | 1178 scoped_refptr<TaskRunner> TestLauncher::GetTaskRunner() { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1216 } | 1211 } |
1217 | 1212 |
1218 std::string snippet(full_output.substr(run_pos)); | 1213 std::string snippet(full_output.substr(run_pos)); |
1219 if (end_pos != std::string::npos) | 1214 if (end_pos != std::string::npos) |
1220 snippet = full_output.substr(run_pos, end_pos - run_pos); | 1215 snippet = full_output.substr(run_pos, end_pos - run_pos); |
1221 | 1216 |
1222 return snippet; | 1217 return snippet; |
1223 } | 1218 } |
1224 | 1219 |
1225 } // namespace base | 1220 } // namespace base |
OLD | NEW |