Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: base/test/launcher/test_launcher.cc

Issue 2736313002: Replace TestLaucher non-leaky LazyInstances with a static pointers. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698