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