process_util_unittest.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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 3// found in the LICENSE file. 4 5#define _CRT_SECURE_NO_WARNINGS 6 7#include <limits> 8 9#include "base/command_line.h" 10#include "base/debug/alias.h" 11#include "base/debug/stack_trace.h" 12#include "base/files/file_path.h" 13#include "base/logging.h" 14#include "base/memory/scoped_ptr.h" 15#include "base/path_service.h" 16#include "base/posix/eintr_wrapper.h" 17#include "base/process/kill.h" 18#include "base/process/launch.h" 19#include "base/process/memory.h" 20#include "base/process/process.h" 21#include "base/process/process_metrics.h" 22#include "base/strings/utf_string_conversions.h" 23#include "base/test/multiprocess_test.h" 24#include "base/test/test_timeouts.h" 25#include "base/third_party/dynamic_annotations/dynamic_annotations.h" 26#include "base/threading/platform_thread.h" 27#include "base/threading/thread.h" 28#include "testing/gtest/include/gtest/gtest.h" 29#include "testing/multiprocess_func_list.h" 30 31#if defined(OS_LINUX) 32#include <glib.h> 33#include <malloc.h> 34#include <sched.h> 35#endif 36#if defined(OS_POSIX) 37#include <dlfcn.h> 38#include <errno.h> 39#include <fcntl.h> 40#include <signal.h> 41#include <sys/resource.h> 42#include <sys/socket.h> 43#include <sys/wait.h> 44#endif 45#if defined(OS_WIN) 46#include <windows.h> 47#endif 48#if defined(OS_MACOSX) 49#include <mach/vm_param.h> 50#include <malloc/malloc.h> 51#endif 52 53using base::FilePath; 54 55namespace { 56 57#if defined(OS_ANDROID) 58const char kShellPath[] = "/system/bin/sh"; 59const char kPosixShell[] = "sh"; 60#else 61const char kShellPath[] = "/bin/sh"; 62const char kPosixShell[] = "bash"; 63#endif 64 65const char kSignalFileSlow[] = "SlowChildProcess.die"; 66const char kSignalFileKill[] = "KilledChildProcess.die"; 67 68#if defined(OS_WIN) 69const int kExpectedStillRunningExitCode = 0x102; 70const int kExpectedKilledExitCode = 1; 71#else 72const int kExpectedStillRunningExitCode = 0; 73#endif 74 75// Sleeps until file filename is created. 76void WaitToDie(const char* filename) { 77 FILE* fp; 78 do { 79 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); 80 fp = fopen(filename, "r"); 81 } while (!fp); 82 fclose(fp); 83} 84 85// Signals children they should die now. 86void SignalChildren(const char* filename) { 87 FILE* fp = fopen(filename, "w"); 88 fclose(fp); 89} 90 91// Using a pipe to the child to wait for an event was considered, but 92// there were cases in the past where pipes caused problems (other 93// libraries closing the fds, child deadlocking). This is a simple 94// case, so it's not worth the risk. Using wait loops is discouraged 95// in most instances. 96base::TerminationStatus WaitForChildTermination(base::ProcessHandle handle, 97 int* exit_code) { 98 // Now we wait until the result is something other than STILL_RUNNING. 99 base::TerminationStatus status = base::TERMINATION_STATUS_STILL_RUNNING; 100 const base::TimeDelta kInterval = base::TimeDelta::FromMilliseconds(20); 101 base::TimeDelta waited; 102 do { 103 status = base::GetTerminationStatus(handle, exit_code); 104 base::PlatformThread::Sleep(kInterval); 105 waited += kInterval; 106 } while (status == base::TERMINATION_STATUS_STILL_RUNNING && 107// Waiting for more time for process termination on android devices. 108#if defined(OS_ANDROID) 109 waited < TestTimeouts::large_test_timeout()); 110#else 111 waited < TestTimeouts::action_max_timeout()); 112#endif 113 114 return status; 115} 116 117} // namespace 118 119class ProcessUtilTest : public base::MultiProcessTest { 120 public: 121#if defined(OS_POSIX) 122 // Spawn a child process that counts how many file descriptors are open. 123 int CountOpenFDsInChild(); 124#endif 125 // Converts the filename to a platform specific filepath. 126 // On Android files can not be created in arbitrary directories. 127 static std::string GetSignalFilePath(const char* filename); 128}; 129 130std::string ProcessUtilTest::GetSignalFilePath(const char* filename) { 131#if !defined(OS_ANDROID) 132 return filename; 133#else 134 FilePath tmp_dir; 135 PathService::Get(base::DIR_CACHE, &tmp_dir); 136 tmp_dir = tmp_dir.Append(filename); 137 return tmp_dir.value(); 138#endif 139} 140 141MULTIPROCESS_TEST_MAIN(SimpleChildProcess) { 142 return 0; 143} 144 145TEST_F(ProcessUtilTest, SpawnChild) { 146 base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false); 147 ASSERT_NE(base::kNullProcessHandle, handle); 148 EXPECT_TRUE(base::WaitForSingleProcess( 149 handle, TestTimeouts::action_max_timeout())); 150 base::CloseProcessHandle(handle); 151} 152 153MULTIPROCESS_TEST_MAIN(SlowChildProcess) { 154 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileSlow).c_str()); 155 return 0; 156} 157 158TEST_F(ProcessUtilTest, KillSlowChild) { 159 const std::string signal_file = 160 ProcessUtilTest::GetSignalFilePath(kSignalFileSlow); 161 remove(signal_file.c_str()); 162 base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false); 163 ASSERT_NE(base::kNullProcessHandle, handle); 164 SignalChildren(signal_file.c_str()); 165 EXPECT_TRUE(base::WaitForSingleProcess( 166 handle, TestTimeouts::action_max_timeout())); 167 base::CloseProcessHandle(handle); 168 remove(signal_file.c_str()); 169} 170 171// Times out on Linux and Win, flakes on other platforms, http://crbug.com/95058 172TEST_F(ProcessUtilTest, DISABLED_GetTerminationStatusExit) { 173 const std::string signal_file = 174 ProcessUtilTest::GetSignalFilePath(kSignalFileSlow); 175 remove(signal_file.c_str()); 176 base::ProcessHandle handle = this->SpawnChild("SlowChildProcess", false); 177 ASSERT_NE(base::kNullProcessHandle, handle); 178 179 int exit_code = 42; 180 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, 181 base::GetTerminationStatus(handle, &exit_code)); 182 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); 183 184 SignalChildren(signal_file.c_str()); 185 exit_code = 42; 186 base::TerminationStatus status = 187 WaitForChildTermination(handle, &exit_code); 188 EXPECT_EQ(base::TERMINATION_STATUS_NORMAL_TERMINATION, status); 189 EXPECT_EQ(0, exit_code); 190 base::CloseProcessHandle(handle); 191 remove(signal_file.c_str()); 192} 193 194#if defined(OS_WIN) 195// TODO(cpu): figure out how to test this in other platforms. 196TEST_F(ProcessUtilTest, GetProcId) { 197 base::ProcessId id1 = base::GetProcId(GetCurrentProcess()); 198 EXPECT_NE(0ul, id1); 199 base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false); 200 ASSERT_NE(base::kNullProcessHandle, handle); 201 base::ProcessId id2 = base::GetProcId(handle); 202 EXPECT_NE(0ul, id2); 203 EXPECT_NE(id1, id2); 204 base::CloseProcessHandle(handle); 205} 206#endif 207 208#if !defined(OS_MACOSX) 209// This test is disabled on Mac, since it's flaky due to ReportCrash 210// taking a variable amount of time to parse and load the debug and 211// symbol data for this unit test's executable before firing the 212// signal handler. 213// 214// TODO(gspencer): turn this test process into a very small program 215// with no symbols (instead of using the multiprocess testing 216// framework) to reduce the ReportCrash overhead. 217const char kSignalFileCrash[] = "CrashingChildProcess.die"; 218 219MULTIPROCESS_TEST_MAIN(CrashingChildProcess) { 220 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileCrash).c_str()); 221#if defined(OS_POSIX) 222 // Have to disable to signal handler for segv so we can get a crash 223 // instead of an abnormal termination through the crash dump handler. 224 ::signal(SIGSEGV, SIG_DFL); 225#endif 226 // Make this process have a segmentation fault. 227 volatile int* oops = NULL; 228 *oops = 0xDEAD; 229 return 1; 230} 231 232// This test intentionally crashes, so we don't need to run it under 233// AddressSanitizer. 234// TODO(jschuh): crbug.com/175753 Fix this in Win64 bots. 235#if defined(ADDRESS_SANITIZER) || (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) 236#define MAYBE_GetTerminationStatusCrash DISABLED_GetTerminationStatusCrash 237#else 238#define MAYBE_GetTerminationStatusCrash GetTerminationStatusCrash 239#endif 240TEST_F(ProcessUtilTest, MAYBE_GetTerminationStatusCrash) { 241 const std::string signal_file = 242 ProcessUtilTest::GetSignalFilePath(kSignalFileCrash); 243 remove(signal_file.c_str()); 244 base::ProcessHandle handle = this->SpawnChild("CrashingChildProcess", 245 false); 246 ASSERT_NE(base::kNullProcessHandle, handle); 247 248 int exit_code = 42; 249 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, 250 base::GetTerminationStatus(handle, &exit_code)); 251 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); 252 253 SignalChildren(signal_file.c_str()); 254 exit_code = 42; 255 base::TerminationStatus status = 256 WaitForChildTermination(handle, &exit_code); 257 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_CRASHED, status); 258 259#if defined(OS_WIN) 260 EXPECT_EQ(0xc0000005, exit_code); 261#elif defined(OS_POSIX) 262 int signaled = WIFSIGNALED(exit_code); 263 EXPECT_NE(0, signaled); 264 int signal = WTERMSIG(exit_code); 265 EXPECT_EQ(SIGSEGV, signal); 266#endif 267 base::CloseProcessHandle(handle); 268 269 // Reset signal handlers back to "normal". 270 base::debug::EnableInProcessStackDumping(); 271 remove(signal_file.c_str()); 272} 273#endif // !defined(OS_MACOSX) 274 275MULTIPROCESS_TEST_MAIN(KilledChildProcess) { 276 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileKill).c_str()); 277#if defined(OS_WIN) 278 // Kill ourselves. 279 HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ::GetCurrentProcessId()); 280 ::TerminateProcess(handle, kExpectedKilledExitCode); 281#elif defined(OS_POSIX) 282 // Send a SIGKILL to this process, just like the OOM killer would. 283 ::kill(getpid(), SIGKILL); 284#endif 285 return 1; 286} 287 288TEST_F(ProcessUtilTest, GetTerminationStatusKill) { 289 const std::string signal_file = 290 ProcessUtilTest::GetSignalFilePath(kSignalFileKill); 291 remove(signal_file.c_str()); 292 base::ProcessHandle handle = this->SpawnChild("KilledChildProcess", 293 false); 294 ASSERT_NE(base::kNullProcessHandle, handle); 295 296 int exit_code = 42; 297 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING, 298 base::GetTerminationStatus(handle, &exit_code)); 299 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code); 300 301 SignalChildren(signal_file.c_str()); 302 exit_code = 42; 303 base::TerminationStatus status = 304 WaitForChildTermination(handle, &exit_code); 305 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_WAS_KILLED, status); 306#if defined(OS_WIN) 307 EXPECT_EQ(kExpectedKilledExitCode, exit_code); 308#elif defined(OS_POSIX) 309 int signaled = WIFSIGNALED(exit_code); 310 EXPECT_NE(0, signaled); 311 int signal = WTERMSIG(exit_code); 312 EXPECT_EQ(SIGKILL, signal); 313#endif 314 base::CloseProcessHandle(handle); 315 remove(signal_file.c_str()); 316} 317 318// Ensure that the priority of a process is restored correctly after 319// backgrounding and restoring. 320// Note: a platform may not be willing or able to lower the priority of 321// a process. The calls to SetProcessBackground should be noops then. 322TEST_F(ProcessUtilTest, SetProcessBackgrounded) { 323 base::ProcessHandle handle = this->SpawnChild("SimpleChildProcess", false); 324 base::Process process(handle); 325 int old_priority = process.GetPriority(); 326#if defined(OS_WIN) 327 EXPECT_TRUE(process.SetProcessBackgrounded(true)); 328 EXPECT_TRUE(process.IsProcessBackgrounded()); 329 EXPECT_TRUE(process.SetProcessBackgrounded(false)); 330 EXPECT_FALSE(process.IsProcessBackgrounded()); 331#else 332 process.SetProcessBackgrounded(true); 333 process.SetProcessBackgrounded(false); 334#endif 335 int new_priority = process.GetPriority(); 336 EXPECT_EQ(old_priority, new_priority); 337} 338 339// Same as SetProcessBackgrounded but to this very process. It uses 340// a different code path at least for Windows. 341TEST_F(ProcessUtilTest, SetProcessBackgroundedSelf) { 342 base::Process process(base::Process::Current().handle()); 343 int old_priority = process.GetPriority(); 344#if defined(OS_WIN) 345 EXPECT_TRUE(process.SetProcessBackgrounded(true)); 346 EXPECT_TRUE(process.IsProcessBackgrounded()); 347 EXPECT_TRUE(process.SetProcessBackgrounded(false)); 348 EXPECT_FALSE(process.IsProcessBackgrounded()); 349#else 350 process.SetProcessBackgrounded(true); 351 process.SetProcessBackgrounded(false); 352#endif 353 int new_priority = process.GetPriority(); 354 EXPECT_EQ(old_priority, new_priority); 355} 356 357#if defined(OS_LINUX) || defined(OS_ANDROID) 358TEST_F(ProcessUtilTest, GetSystemMemoryInfo) { 359 base::SystemMemoryInfoKB info; 360 EXPECT_TRUE(base::GetSystemMemoryInfo(&info)); 361 362 // Ensure each field received a value. 363 EXPECT_GT(info.total, 0); 364 EXPECT_GT(info.free, 0); 365 EXPECT_GT(info.buffers, 0); 366 EXPECT_GT(info.cached, 0); 367 EXPECT_GT(info.active_anon, 0); 368 EXPECT_GT(info.inactive_anon, 0); 369 EXPECT_GT(info.active_file, 0); 370 EXPECT_GT(info.inactive_file, 0); 371 372 // All the values should be less than the total amount of memory. 373 EXPECT_LT(info.free, info.total); 374 EXPECT_LT(info.buffers, info.total); 375 EXPECT_LT(info.cached, info.total); 376 EXPECT_LT(info.active_anon, info.total); 377 EXPECT_LT(info.inactive_anon, info.total); 378 EXPECT_LT(info.active_file, info.total); 379 EXPECT_LT(info.inactive_file, info.total); 380 381#if defined(OS_CHROMEOS) 382 // Chrome OS exposes shmem. 383 EXPECT_GT(info.shmem, 0); 384 EXPECT_LT(info.shmem, info.total); 385 // Chrome unit tests are not run on actual Chrome OS hardware, so gem_objects 386 // and gem_size cannot be tested here. 387#endif 388} 389#endif // defined(OS_LINUX) || defined(OS_ANDROID) 390 391// TODO(estade): if possible, port these 2 tests. 392#if defined(OS_WIN) 393TEST_F(ProcessUtilTest, CalcFreeMemory) { 394 scoped_ptr<base::ProcessMetrics> metrics( 395 base::ProcessMetrics::CreateProcessMetrics(::GetCurrentProcess())); 396 ASSERT_TRUE(NULL != metrics.get()); 397 398 bool using_tcmalloc = false; 399 400 // Detect if we are using tcmalloc 401#if !defined(NO_TCMALLOC) 402 const char* chrome_allocator = getenv("CHROME_ALLOCATOR"); 403 if (!chrome_allocator || _stricmp(chrome_allocator, "tcmalloc") == 0) 404 using_tcmalloc = true; 405#endif 406 407 // Typical values here is ~1900 for total and ~1000 for largest. Obviously 408 // it depends in what other tests have done to this process. 409 base::FreeMBytes free_mem1 = {0}; 410 EXPECT_TRUE(metrics->CalculateFreeMemory(&free_mem1)); 411 EXPECT_LT(10u, free_mem1.total); 412 EXPECT_LT(10u, free_mem1.largest); 413 EXPECT_GT(2048u, free_mem1.total); 414 EXPECT_GT(2048u, free_mem1.largest); 415 EXPECT_GE(free_mem1.total, free_mem1.largest); 416 EXPECT_TRUE(NULL != free_mem1.largest_ptr); 417 418 // Allocate 20M and check again. It should have gone down. 419 const int kAllocMB = 20; 420 scoped_ptr<char[]> alloc(new char[kAllocMB * 1024 * 1024]); 421 size_t expected_total = free_mem1.total - kAllocMB; 422 size_t expected_largest = free_mem1.largest; 423 424 base::FreeMBytes free_mem2 = {0}; 425 EXPECT_TRUE(metrics->CalculateFreeMemory(&free_mem2)); 426 EXPECT_GE(free_mem2.total, free_mem2.largest); 427 // This test is flaky when using tcmalloc, because tcmalloc 428 // allocation strategy sometimes results in less than the 429 // full drop of 20Mb of free memory. 430 if (!using_tcmalloc) 431 EXPECT_GE(expected_total, free_mem2.total); 432 EXPECT_GE(expected_largest, free_mem2.largest); 433 EXPECT_TRUE(NULL != free_mem2.largest_ptr); 434} 435 436TEST_F(ProcessUtilTest, GetAppOutput) { 437 // Let's create a decently long message. 438 std::string message; 439 for (int i = 0; i < 1025; i++) { // 1025 so it does not end on a kilo-byte 440 // boundary. 441 message += "Hello!"; 442 } 443 // cmd.exe's echo always adds a \r\n to its output. 444 std::string expected(message); 445 expected += "\r\n"; 446 447 FilePath cmd(L"cmd.exe"); 448 CommandLine cmd_line(cmd); 449 cmd_line.AppendArg("/c"); 450 cmd_line.AppendArg("echo " + message + ""); 451 std::string output; 452 ASSERT_TRUE(base::GetAppOutput(cmd_line, &output)); 453 EXPECT_EQ(expected, output); 454 455 // Let's make sure stderr is ignored. 456 CommandLine other_cmd_line(cmd); 457 other_cmd_line.AppendArg("/c"); 458 // http://msdn.microsoft.com/library/cc772622.aspx 459 cmd_line.AppendArg("echo " + message + " >&2"); 460 output.clear(); 461 ASSERT_TRUE(base::GetAppOutput(other_cmd_line, &output)); 462 EXPECT_EQ("", output); 463} 464 465TEST_F(ProcessUtilTest, LaunchAsUser) { 466 base::UserTokenHandle token; 467 ASSERT_TRUE(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token)); 468 std::wstring cmdline = 469 this->MakeCmdLine("SimpleChildProcess", false).GetCommandLineString(); 470 base::LaunchOptions options; 471 options.as_user = token; 472 EXPECT_TRUE(base::LaunchProcess(cmdline, options, NULL)); 473} 474 475#endif // defined(OS_WIN) 476 477#if defined(OS_POSIX) 478 479namespace { 480 481// Returns the maximum number of files that a process can have open. 482// Returns 0 on error. 483int GetMaxFilesOpenInProcess() { 484 struct rlimit rlim; 485 if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) { 486 return 0; 487 } 488 489 // rlim_t is a uint64 - clip to maxint. We do this since FD #s are ints 490 // which are all 32 bits on the supported platforms. 491 rlim_t max_int = static_cast<rlim_t>(std::numeric_limits<int32>::max()); 492 if (rlim.rlim_cur > max_int) { 493 return max_int; 494 } 495 496 return rlim.rlim_cur; 497} 498 499const int kChildPipe = 20; // FD # for write end of pipe in child process. 500 501} // namespace 502 503MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess) { 504 // This child process counts the number of open FDs, it then writes that 505 // number out to a pipe connected to the parent. 506 int num_open_files = 0; 507 int write_pipe = kChildPipe; 508 int max_files = GetMaxFilesOpenInProcess(); 509 for (int i = STDERR_FILENO + 1; i < max_files; i++) { 510 if (i != kChildPipe) { 511 int fd; 512 if ((fd = HANDLE_EINTR(dup(i))) != -1) { 513 close(fd); 514 num_open_files += 1; 515 } 516 } 517 } 518 519 int written = HANDLE_EINTR(write(write_pipe, &num_open_files, 520 sizeof(num_open_files))); 521 DCHECK_EQ(static_cast<size_t>(written), sizeof(num_open_files)); 522 int ret = HANDLE_EINTR(close(write_pipe)); 523 DPCHECK(ret == 0); 524 525 return 0; 526} 527 528int ProcessUtilTest::CountOpenFDsInChild() { 529 int fds[2]; 530 if (pipe(fds) < 0) 531 NOTREACHED(); 532 533 base::FileHandleMappingVector fd_mapping_vec; 534 fd_mapping_vec.push_back(std::pair<int, int>(fds[1], kChildPipe)); 535 base::ProcessHandle handle = this->SpawnChild( 536 "ProcessUtilsLeakFDChildProcess", fd_mapping_vec, false); 537 CHECK(handle); 538 int ret = HANDLE_EINTR(close(fds[1])); 539 DPCHECK(ret == 0); 540 541 // Read number of open files in client process from pipe; 542 int num_open_files = -1; 543 ssize_t bytes_read = 544 HANDLE_EINTR(read(fds[0], &num_open_files, sizeof(num_open_files))); 545 CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(num_open_files))); 546 547#if defined(THREAD_SANITIZER) || defined(USE_HEAPCHECKER) 548 // Compiler-based ThreadSanitizer makes this test slow. 549 CHECK(base::WaitForSingleProcess(handle, base::TimeDelta::FromSeconds(3))); 550#else 551 CHECK(base::WaitForSingleProcess(handle, base::TimeDelta::FromSeconds(1))); 552#endif 553 base::CloseProcessHandle(handle); 554 ret = HANDLE_EINTR(close(fds[0])); 555 DPCHECK(ret == 0); 556 557 return num_open_files; 558} 559 560#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) 561// ProcessUtilTest.FDRemapping is flaky when ran under xvfb-run on Precise. 562// The problem is 100% reproducible with both ASan and TSan. 563// See http://crbug.com/136720. 564#define MAYBE_FDRemapping DISABLED_FDRemapping 565#else 566#define MAYBE_FDRemapping FDRemapping 567#endif 568TEST_F(ProcessUtilTest, MAYBE_FDRemapping) { 569 int fds_before = CountOpenFDsInChild(); 570 571 // open some dummy fds to make sure they don't propagate over to the 572 // child process. 573 int dev_null = open("/dev/null", O_RDONLY); 574 int sockets[2]; 575 socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); 576 577 int fds_after = CountOpenFDsInChild(); 578 579 ASSERT_EQ(fds_after, fds_before); 580 581 int ret; 582 ret = HANDLE_EINTR(close(sockets[0])); 583 DPCHECK(ret == 0); 584 ret = HANDLE_EINTR(close(sockets[1])); 585 DPCHECK(ret == 0); 586 ret = HANDLE_EINTR(close(dev_null)); 587 DPCHECK(ret == 0); 588} 589 590namespace { 591 592std::string TestLaunchProcess(const base::EnvironmentMap& env_changes, 593 const int clone_flags) { 594 std::vector<std::string> args; 595 base::FileHandleMappingVector fds_to_remap; 596 597 args.push_back(kPosixShell); 598 args.push_back("-c"); 599 args.push_back("echo $BASE_TEST"); 600 601 int fds[2]; 602 PCHECK(pipe(fds) == 0); 603 604 fds_to_remap.push_back(std::make_pair(fds[1], 1)); 605 base::LaunchOptions options; 606 options.wait = true; 607 options.environ = env_changes; 608 options.fds_to_remap = &fds_to_remap; 609#if defined(OS_LINUX) 610 options.clone_flags = clone_flags; 611#else 612 CHECK_EQ(0, clone_flags); 613#endif // OS_LINUX 614 EXPECT_TRUE(base::LaunchProcess(args, options, NULL)); 615 PCHECK(HANDLE_EINTR(close(fds[1])) == 0); 616 617 char buf[512]; 618 const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf))); 619 PCHECK(n > 0); 620 621 PCHECK(HANDLE_EINTR(close(fds[0])) == 0); 622 623 return std::string(buf, n); 624} 625 626const char kLargeString[] = 627 "0123456789012345678901234567890123456789012345678901234567890123456789" 628 "0123456789012345678901234567890123456789012345678901234567890123456789" 629 "0123456789012345678901234567890123456789012345678901234567890123456789" 630 "0123456789012345678901234567890123456789012345678901234567890123456789" 631 "0123456789012345678901234567890123456789012345678901234567890123456789" 632 "0123456789012345678901234567890123456789012345678901234567890123456789" 633 "0123456789012345678901234567890123456789012345678901234567890123456789"; 634 635} // namespace 636 637TEST_F(ProcessUtilTest, LaunchProcess) { 638 base::EnvironmentMap env_changes; 639 const int no_clone_flags = 0; 640 641 const char kBaseTest[] = "BASE_TEST"; 642 643 env_changes[kBaseTest] = "bar"; 644 EXPECT_EQ("bar\n", TestLaunchProcess(env_changes, no_clone_flags)); 645 env_changes.clear(); 646 647 EXPECT_EQ(0, setenv(kBaseTest, "testing", 1 /* override */)); 648 EXPECT_EQ("testing\n", TestLaunchProcess(env_changes, no_clone_flags)); 649 650 env_changes[kBaseTest] = std::string(); 651 EXPECT_EQ("\n", TestLaunchProcess(env_changes, no_clone_flags)); 652 653 env_changes[kBaseTest] = "foo"; 654 EXPECT_EQ("foo\n", TestLaunchProcess(env_changes, no_clone_flags)); 655 656 env_changes.clear(); 657 EXPECT_EQ(0, setenv(kBaseTest, kLargeString, 1 /* override */)); 658 EXPECT_EQ(std::string(kLargeString) + "\n", 659 TestLaunchProcess(env_changes, no_clone_flags)); 660 661 env_changes[kBaseTest] = "wibble"; 662 EXPECT_EQ("wibble\n", TestLaunchProcess(env_changes, no_clone_flags)); 663 664#if defined(OS_LINUX) 665 // Test a non-trival value for clone_flags. 666 // Don't test on Valgrind as it has limited support for clone(). 667 if (!RunningOnValgrind()) { 668 EXPECT_EQ("wibble\n", TestLaunchProcess(env_changes, CLONE_FS | SIGCHLD)); 669 } 670#endif 671} 672 673TEST_F(ProcessUtilTest, GetAppOutput) { 674 std::string output; 675 676#if defined(OS_ANDROID) 677 std::vector<std::string> argv; 678 argv.push_back("sh"); // Instead of /bin/sh, force path search to find it. 679 argv.push_back("-c"); 680 681 argv.push_back("exit 0"); 682 EXPECT_TRUE(base::GetAppOutput(CommandLine(argv), &output)); 683 EXPECT_STREQ("", output.c_str()); 684 685 argv[2] = "exit 1"; 686 EXPECT_FALSE(base::GetAppOutput(CommandLine(argv), &output)); 687 EXPECT_STREQ("", output.c_str()); 688 689 argv[2] = "echo foobar42"; 690 EXPECT_TRUE(base::GetAppOutput(CommandLine(argv), &output)); 691 EXPECT_STREQ("foobar42\n", output.c_str()); 692#else 693 EXPECT_TRUE(base::GetAppOutput(CommandLine(FilePath("true")), &output)); 694 EXPECT_STREQ("", output.c_str()); 695 696 EXPECT_FALSE(base::GetAppOutput(CommandLine(FilePath("false")), &output)); 697 698 std::vector<std::string> argv; 699 argv.push_back("/bin/echo"); 700 argv.push_back("-n"); 701 argv.push_back("foobar42"); 702 EXPECT_TRUE(base::GetAppOutput(CommandLine(argv), &output)); 703 EXPECT_STREQ("foobar42", output.c_str()); 704#endif // defined(OS_ANDROID) 705} 706 707TEST_F(ProcessUtilTest, GetAppOutputRestricted) { 708 // Unfortunately, since we can't rely on the path, we need to know where 709 // everything is. So let's use /bin/sh, which is on every POSIX system, and 710 // its built-ins. 711 std::vector<std::string> argv; 712 argv.push_back(std::string(kShellPath)); // argv[0] 713 argv.push_back("-c"); // argv[1] 714 715 // On success, should set |output|. We use |/bin/sh -c 'exit 0'| instead of 716 // |true| since the location of the latter may be |/bin| or |/usr/bin| (and we 717 // need absolute paths). 718 argv.push_back("exit 0"); // argv[2]; equivalent to "true" 719 std::string output = "abc"; 720 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 100)); 721 EXPECT_STREQ("", output.c_str()); 722 723 argv[2] = "exit 1"; // equivalent to "false" 724 output = "before"; 725 EXPECT_FALSE(base::GetAppOutputRestricted(CommandLine(argv), 726 &output, 100)); 727 EXPECT_STREQ("", output.c_str()); 728 729 // Amount of output exactly equal to space allowed. 730 argv[2] = "echo 123456789"; // (the sh built-in doesn't take "-n") 731 output.clear(); 732 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 733 EXPECT_STREQ("123456789\n", output.c_str()); 734 735 // Amount of output greater than space allowed. 736 output.clear(); 737 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 5)); 738 EXPECT_STREQ("12345", output.c_str()); 739 740 // Amount of output less than space allowed. 741 output.clear(); 742 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 15)); 743 EXPECT_STREQ("123456789\n", output.c_str()); 744 745 // Zero space allowed. 746 output = "abc"; 747 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 0)); 748 EXPECT_STREQ("", output.c_str()); 749} 750 751#if !defined(OS_MACOSX) && !defined(OS_OPENBSD) 752// TODO(benwells): GetAppOutputRestricted should terminate applications 753// with SIGPIPE when we have enough output. http://crbug.com/88502 754TEST_F(ProcessUtilTest, GetAppOutputRestrictedSIGPIPE) { 755 std::vector<std::string> argv; 756 std::string output; 757 758 argv.push_back(std::string(kShellPath)); // argv[0] 759 argv.push_back("-c"); 760#if defined(OS_ANDROID) 761 argv.push_back("while echo 12345678901234567890; do :; done"); 762 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 763 EXPECT_STREQ("1234567890", output.c_str()); 764#else 765 argv.push_back("yes"); 766 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 767 EXPECT_STREQ("y\ny\ny\ny\ny\n", output.c_str()); 768#endif 769} 770#endif 771 772#if defined(ADDRESS_SANITIZER) && defined(OS_MACOSX) && \ 773 defined(ARCH_CPU_64_BITS) 774// Times out under AddressSanitizer on 64-bit OS X, see 775// http://crbug.com/298197. 776#define MAYBE_GetAppOutputRestrictedNoZombies \ 777 DISABLED_GetAppOutputRestrictedNoZombies 778#else 779#define MAYBE_GetAppOutputRestrictedNoZombies GetAppOutputRestrictedNoZombies 780#endif 781TEST_F(ProcessUtilTest, MAYBE_GetAppOutputRestrictedNoZombies) { 782 std::vector<std::string> argv; 783 784 argv.push_back(std::string(kShellPath)); // argv[0] 785 argv.push_back("-c"); // argv[1] 786 argv.push_back("echo 123456789012345678901234567890"); // argv[2] 787 788 // Run |GetAppOutputRestricted()| 300 (> default per-user processes on Mac OS 789 // 10.5) times with an output buffer big enough to capture all output. 790 for (int i = 0; i < 300; i++) { 791 std::string output; 792 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 100)); 793 EXPECT_STREQ("123456789012345678901234567890\n", output.c_str()); 794 } 795 796 // Ditto, but with an output buffer too small to capture all output. 797 for (int i = 0; i < 300; i++) { 798 std::string output; 799 EXPECT_TRUE(base::GetAppOutputRestricted(CommandLine(argv), &output, 10)); 800 EXPECT_STREQ("1234567890", output.c_str()); 801 } 802} 803 804TEST_F(ProcessUtilTest, GetAppOutputWithExitCode) { 805 // Test getting output from a successful application. 806 std::vector<std::string> argv; 807 std::string output; 808 int exit_code; 809 argv.push_back(std::string(kShellPath)); // argv[0] 810 argv.push_back("-c"); // argv[1] 811 argv.push_back("echo foo"); // argv[2]; 812 EXPECT_TRUE(base::GetAppOutputWithExitCode(CommandLine(argv), &output, 813 &exit_code)); 814 EXPECT_STREQ("foo\n", output.c_str()); 815 EXPECT_EQ(exit_code, 0); 816 817 // Test getting output from an application which fails with a specific exit 818 // code. 819 output.clear(); 820 argv[2] = "echo foo; exit 2"; 821 EXPECT_TRUE(base::GetAppOutputWithExitCode(CommandLine(argv), &output, 822 &exit_code)); 823 EXPECT_STREQ("foo\n", output.c_str()); 824 EXPECT_EQ(exit_code, 2); 825} 826 827TEST_F(ProcessUtilTest, GetParentProcessId) { 828 base::ProcessId ppid = base::GetParentProcessId(base::GetCurrentProcId()); 829 EXPECT_EQ(ppid, getppid()); 830} 831 832#if defined(OS_LINUX) || defined(OS_ANDROID) 833TEST_F(ProcessUtilTest, ParseProcStatCPU) { 834 // /proc/self/stat for a process running "top". 835 const char kTopStat[] = "960 (top) S 16230 960 16230 34818 960 " 836 "4202496 471 0 0 0 " 837 "12 16 0 0 " // <- These are the goods. 838 "20 0 1 0 121946157 15077376 314 18446744073709551615 4194304 " 839 "4246868 140733983044336 18446744073709551615 140244213071219 " 840 "0 0 0 138047495 0 0 0 17 1 0 0 0 0 0"; 841 EXPECT_EQ(12 + 16, base::ParseProcStatCPU(kTopStat)); 842 843 // cat /proc/self/stat on a random other machine I have. 844 const char kSelfStat[] = "5364 (cat) R 5354 5364 5354 34819 5364 " 845 "0 142 0 0 0 " 846 "0 0 0 0 " // <- No CPU, apparently. 847 "16 0 1 0 1676099790 2957312 114 4294967295 134512640 134528148 " 848 "3221224832 3221224344 3086339742 0 0 0 0 0 0 0 17 0 0 0"; 849 850 EXPECT_EQ(0, base::ParseProcStatCPU(kSelfStat)); 851} 852 853// Disable on Android because base_unittests runs inside a Dalvik VM that 854// starts and stop threads (crbug.com/175563). 855#if !defined(OS_ANDROID) 856TEST_F(ProcessUtilTest, GetNumberOfThreads) { 857 const base::ProcessHandle current = base::GetCurrentProcessHandle(); 858 const int initial_threads = base::GetNumberOfThreads(current); 859 ASSERT_GT(initial_threads, 0); 860 const int kNumAdditionalThreads = 10; 861 { 862 scoped_ptr<base::Thread> my_threads[kNumAdditionalThreads]; 863 for (int i = 0; i < kNumAdditionalThreads; ++i) { 864 my_threads[i].reset(new base::Thread("GetNumberOfThreadsTest")); 865 my_threads[i]->Start(); 866 ASSERT_EQ(base::GetNumberOfThreads(current), initial_threads + 1 + i); 867 } 868 } 869 // The Thread destructor will stop them. 870 ASSERT_EQ(initial_threads, base::GetNumberOfThreads(current)); 871} 872#endif // !defined(OS_ANDROID) 873 874#endif // defined(OS_LINUX) || defined(OS_ANDROID) 875 876// TODO(port): port those unit tests. 877bool IsProcessDead(base::ProcessHandle child) { 878 // waitpid() will actually reap the process which is exactly NOT what we 879 // want to test for. The good thing is that if it can't find the process 880 // we'll get a nice value for errno which we can test for. 881 const pid_t result = HANDLE_EINTR(waitpid(child, NULL, WNOHANG)); 882 return result == -1 && errno == ECHILD; 883} 884 885TEST_F(ProcessUtilTest, DelayedTermination) { 886 base::ProcessHandle child_process = 887 SpawnChild("process_util_test_never_die", false); 888 ASSERT_TRUE(child_process); 889 base::EnsureProcessTerminated(child_process); 890 base::WaitForSingleProcess(child_process, base::TimeDelta::FromSeconds(5)); 891 892 // Check that process was really killed. 893 EXPECT_TRUE(IsProcessDead(child_process)); 894 base::CloseProcessHandle(child_process); 895} 896 897MULTIPROCESS_TEST_MAIN(process_util_test_never_die) { 898 while (1) { 899 sleep(500); 900 } 901 return 0; 902} 903 904TEST_F(ProcessUtilTest, ImmediateTermination) { 905 base::ProcessHandle child_process = 906 SpawnChild("process_util_test_die_immediately", false); 907 ASSERT_TRUE(child_process); 908 // Give it time to die. 909 sleep(2); 910 base::EnsureProcessTerminated(child_process); 911 912 // Check that process was really killed. 913 EXPECT_TRUE(IsProcessDead(child_process)); 914 base::CloseProcessHandle(child_process); 915} 916 917MULTIPROCESS_TEST_MAIN(process_util_test_die_immediately) { 918 return 0; 919} 920 921#endif // defined(OS_POSIX) 922