Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / base / process / process_util_unittest.cc
blobcf83aa751815406817e88d8beacdd41ecd82d41a
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.
5 #define _CRT_SECURE_NO_WARNINGS
7 #include <limits>
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/files/file_util.h"
14 #include "base/files/scoped_file.h"
15 #include "base/logging.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/path_service.h"
18 #include "base/posix/eintr_wrapper.h"
19 #include "base/process/kill.h"
20 #include "base/process/launch.h"
21 #include "base/process/memory.h"
22 #include "base/process/process.h"
23 #include "base/process/process_metrics.h"
24 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "base/synchronization/waitable_event.h"
27 #include "base/test/multiprocess_test.h"
28 #include "base/test/test_timeouts.h"
29 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
30 #include "base/threading/platform_thread.h"
31 #include "base/threading/thread.h"
32 #include "build/build_config.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34 #include "testing/multiprocess_func_list.h"
36 #if defined(OS_LINUX)
37 #include <malloc.h>
38 #include <sched.h>
39 #include <sys/syscall.h>
40 #endif
41 #if defined(OS_POSIX)
42 #include <dlfcn.h>
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <sched.h>
46 #include <signal.h>
47 #include <sys/resource.h>
48 #include <sys/socket.h>
49 #include <sys/types.h>
50 #include <sys/wait.h>
51 #include <unistd.h>
52 #endif
53 #if defined(OS_WIN)
54 #include <windows.h>
55 #include "base/win/windows_version.h"
56 #endif
57 #if defined(OS_MACOSX)
58 #include <mach/vm_param.h>
59 #include <malloc/malloc.h>
60 #include "base/mac/mac_util.h"
61 #endif
63 using base::FilePath;
65 namespace {
67 const char kSignalFileSlow[] = "SlowChildProcess.die";
68 const char kSignalFileKill[] = "KilledChildProcess.die";
70 #if defined(OS_POSIX)
71 const char kSignalFileTerm[] = "TerminatedChildProcess.die";
73 #if defined(OS_ANDROID)
74 const char kShellPath[] = "/system/bin/sh";
75 const char kPosixShell[] = "sh";
76 #else
77 const char kShellPath[] = "/bin/sh";
78 const char kPosixShell[] = "sh";
79 #endif
80 #endif // defined(OS_POSIX)
82 #if defined(OS_WIN)
83 const int kExpectedStillRunningExitCode = 0x102;
84 const int kExpectedKilledExitCode = 1;
85 #else
86 const int kExpectedStillRunningExitCode = 0;
87 #endif
89 // Sleeps until file filename is created.
90 void WaitToDie(const char* filename) {
91 FILE* fp;
92 do {
93 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
94 fp = fopen(filename, "r");
95 } while (!fp);
96 fclose(fp);
99 // Signals children they should die now.
100 void SignalChildren(const char* filename) {
101 FILE* fp = fopen(filename, "w");
102 fclose(fp);
105 // Using a pipe to the child to wait for an event was considered, but
106 // there were cases in the past where pipes caused problems (other
107 // libraries closing the fds, child deadlocking). This is a simple
108 // case, so it's not worth the risk. Using wait loops is discouraged
109 // in most instances.
110 base::TerminationStatus WaitForChildTermination(base::ProcessHandle handle,
111 int* exit_code) {
112 // Now we wait until the result is something other than STILL_RUNNING.
113 base::TerminationStatus status = base::TERMINATION_STATUS_STILL_RUNNING;
114 const base::TimeDelta kInterval = base::TimeDelta::FromMilliseconds(20);
115 base::TimeDelta waited;
116 do {
117 status = base::GetTerminationStatus(handle, exit_code);
118 base::PlatformThread::Sleep(kInterval);
119 waited += kInterval;
120 } while (status == base::TERMINATION_STATUS_STILL_RUNNING &&
121 waited < TestTimeouts::action_max_timeout());
123 return status;
126 } // namespace
128 class ProcessUtilTest : public base::MultiProcessTest {
129 public:
130 #if defined(OS_POSIX)
131 // Spawn a child process that counts how many file descriptors are open.
132 int CountOpenFDsInChild();
133 #endif
134 // Converts the filename to a platform specific filepath.
135 // On Android files can not be created in arbitrary directories.
136 static std::string GetSignalFilePath(const char* filename);
139 std::string ProcessUtilTest::GetSignalFilePath(const char* filename) {
140 #if !defined(OS_ANDROID)
141 return filename;
142 #else
143 FilePath tmp_dir;
144 PathService::Get(base::DIR_CACHE, &tmp_dir);
145 tmp_dir = tmp_dir.Append(filename);
146 return tmp_dir.value();
147 #endif
150 MULTIPROCESS_TEST_MAIN(SimpleChildProcess) {
151 return 0;
154 // TODO(viettrungluu): This should be in a "MultiProcessTestTest".
155 TEST_F(ProcessUtilTest, SpawnChild) {
156 base::Process process = SpawnChild("SimpleChildProcess");
157 ASSERT_TRUE(process.IsValid());
158 int exit_code;
159 EXPECT_TRUE(process.WaitForExitWithTimeout(
160 TestTimeouts::action_max_timeout(), &exit_code));
163 MULTIPROCESS_TEST_MAIN(SlowChildProcess) {
164 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileSlow).c_str());
165 return 0;
168 TEST_F(ProcessUtilTest, KillSlowChild) {
169 const std::string signal_file =
170 ProcessUtilTest::GetSignalFilePath(kSignalFileSlow);
171 remove(signal_file.c_str());
172 base::Process process = SpawnChild("SlowChildProcess");
173 ASSERT_TRUE(process.IsValid());
174 SignalChildren(signal_file.c_str());
175 int exit_code;
176 EXPECT_TRUE(process.WaitForExitWithTimeout(
177 TestTimeouts::action_max_timeout(), &exit_code));
178 remove(signal_file.c_str());
181 // Times out on Linux and Win, flakes on other platforms, http://crbug.com/95058
182 TEST_F(ProcessUtilTest, DISABLED_GetTerminationStatusExit) {
183 const std::string signal_file =
184 ProcessUtilTest::GetSignalFilePath(kSignalFileSlow);
185 remove(signal_file.c_str());
186 base::Process process = SpawnChild("SlowChildProcess");
187 ASSERT_TRUE(process.IsValid());
189 int exit_code = 42;
190 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
191 base::GetTerminationStatus(process.Handle(), &exit_code));
192 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
194 SignalChildren(signal_file.c_str());
195 exit_code = 42;
196 base::TerminationStatus status =
197 WaitForChildTermination(process.Handle(), &exit_code);
198 EXPECT_EQ(base::TERMINATION_STATUS_NORMAL_TERMINATION, status);
199 EXPECT_EQ(0, exit_code);
200 remove(signal_file.c_str());
203 #if defined(OS_WIN)
204 // TODO(cpu): figure out how to test this in other platforms.
205 TEST_F(ProcessUtilTest, GetProcId) {
206 base::ProcessId id1 = base::GetProcId(GetCurrentProcess());
207 EXPECT_NE(0ul, id1);
208 base::Process process = SpawnChild("SimpleChildProcess");
209 ASSERT_TRUE(process.IsValid());
210 base::ProcessId id2 = process.Pid();
211 EXPECT_NE(0ul, id2);
212 EXPECT_NE(id1, id2);
214 #endif
216 #if !defined(OS_MACOSX)
217 // This test is disabled on Mac, since it's flaky due to ReportCrash
218 // taking a variable amount of time to parse and load the debug and
219 // symbol data for this unit test's executable before firing the
220 // signal handler.
222 // TODO(gspencer): turn this test process into a very small program
223 // with no symbols (instead of using the multiprocess testing
224 // framework) to reduce the ReportCrash overhead.
225 const char kSignalFileCrash[] = "CrashingChildProcess.die";
227 MULTIPROCESS_TEST_MAIN(CrashingChildProcess) {
228 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileCrash).c_str());
229 #if defined(OS_POSIX)
230 // Have to disable to signal handler for segv so we can get a crash
231 // instead of an abnormal termination through the crash dump handler.
232 ::signal(SIGSEGV, SIG_DFL);
233 #endif
234 // Make this process have a segmentation fault.
235 volatile int* oops = NULL;
236 *oops = 0xDEAD;
237 return 1;
240 // This test intentionally crashes, so we don't need to run it under
241 // AddressSanitizer.
242 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
243 #define MAYBE_GetTerminationStatusCrash DISABLED_GetTerminationStatusCrash
244 #else
245 #define MAYBE_GetTerminationStatusCrash GetTerminationStatusCrash
246 #endif
247 TEST_F(ProcessUtilTest, MAYBE_GetTerminationStatusCrash) {
248 const std::string signal_file =
249 ProcessUtilTest::GetSignalFilePath(kSignalFileCrash);
250 remove(signal_file.c_str());
251 base::Process process = SpawnChild("CrashingChildProcess");
252 ASSERT_TRUE(process.IsValid());
254 int exit_code = 42;
255 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
256 base::GetTerminationStatus(process.Handle(), &exit_code));
257 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
259 SignalChildren(signal_file.c_str());
260 exit_code = 42;
261 base::TerminationStatus status =
262 WaitForChildTermination(process.Handle(), &exit_code);
263 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_CRASHED, status);
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
274 // Reset signal handlers back to "normal".
275 base::debug::EnableInProcessStackDumping();
276 remove(signal_file.c_str());
278 #endif // !defined(OS_MACOSX)
280 MULTIPROCESS_TEST_MAIN(KilledChildProcess) {
281 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileKill).c_str());
282 #if defined(OS_WIN)
283 // Kill ourselves.
284 HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ::GetCurrentProcessId());
285 ::TerminateProcess(handle, kExpectedKilledExitCode);
286 #elif defined(OS_POSIX)
287 // Send a SIGKILL to this process, just like the OOM killer would.
288 ::kill(getpid(), SIGKILL);
289 #endif
290 return 1;
293 #if defined(OS_POSIX)
294 MULTIPROCESS_TEST_MAIN(TerminatedChildProcess) {
295 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileTerm).c_str());
296 // Send a SIGTERM to this process.
297 ::kill(getpid(), SIGTERM);
298 return 1;
300 #endif
302 TEST_F(ProcessUtilTest, GetTerminationStatusSigKill) {
303 const std::string signal_file =
304 ProcessUtilTest::GetSignalFilePath(kSignalFileKill);
305 remove(signal_file.c_str());
306 base::Process process = SpawnChild("KilledChildProcess");
307 ASSERT_TRUE(process.IsValid());
309 int exit_code = 42;
310 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
311 base::GetTerminationStatus(process.Handle(), &exit_code));
312 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
314 SignalChildren(signal_file.c_str());
315 exit_code = 42;
316 base::TerminationStatus status =
317 WaitForChildTermination(process.Handle(), &exit_code);
318 #if defined(OS_CHROMEOS)
319 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM, status);
320 #else
321 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_WAS_KILLED, status);
322 #endif
324 #if defined(OS_WIN)
325 EXPECT_EQ(kExpectedKilledExitCode, exit_code);
326 #elif defined(OS_POSIX)
327 int signaled = WIFSIGNALED(exit_code);
328 EXPECT_NE(0, signaled);
329 int signal = WTERMSIG(exit_code);
330 EXPECT_EQ(SIGKILL, signal);
331 #endif
332 remove(signal_file.c_str());
335 #if defined(OS_POSIX)
336 TEST_F(ProcessUtilTest, GetTerminationStatusSigTerm) {
337 const std::string signal_file =
338 ProcessUtilTest::GetSignalFilePath(kSignalFileTerm);
339 remove(signal_file.c_str());
340 base::Process process = SpawnChild("TerminatedChildProcess");
341 ASSERT_TRUE(process.IsValid());
343 int exit_code = 42;
344 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
345 base::GetTerminationStatus(process.Handle(), &exit_code));
346 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
348 SignalChildren(signal_file.c_str());
349 exit_code = 42;
350 base::TerminationStatus status =
351 WaitForChildTermination(process.Handle(), &exit_code);
352 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_WAS_KILLED, status);
354 int signaled = WIFSIGNALED(exit_code);
355 EXPECT_NE(0, signaled);
356 int signal = WTERMSIG(exit_code);
357 EXPECT_EQ(SIGTERM, signal);
358 remove(signal_file.c_str());
360 #endif
362 #if defined(OS_WIN)
363 // TODO(estade): if possible, port this test.
364 TEST_F(ProcessUtilTest, GetAppOutput) {
365 // Let's create a decently long message.
366 std::string message;
367 for (int i = 0; i < 1025; i++) { // 1025 so it does not end on a kilo-byte
368 // boundary.
369 message += "Hello!";
371 // cmd.exe's echo always adds a \r\n to its output.
372 std::string expected(message);
373 expected += "\r\n";
375 FilePath cmd(L"cmd.exe");
376 base::CommandLine cmd_line(cmd);
377 cmd_line.AppendArg("/c");
378 cmd_line.AppendArg("echo " + message + "");
379 std::string output;
380 ASSERT_TRUE(base::GetAppOutput(cmd_line, &output));
381 EXPECT_EQ(expected, output);
383 // Let's make sure stderr is ignored.
384 base::CommandLine other_cmd_line(cmd);
385 other_cmd_line.AppendArg("/c");
386 // http://msdn.microsoft.com/library/cc772622.aspx
387 cmd_line.AppendArg("echo " + message + " >&2");
388 output.clear();
389 ASSERT_TRUE(base::GetAppOutput(other_cmd_line, &output));
390 EXPECT_EQ("", output);
393 // TODO(estade): if possible, port this test.
394 TEST_F(ProcessUtilTest, LaunchAsUser) {
395 base::UserTokenHandle token;
396 ASSERT_TRUE(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token));
397 base::LaunchOptions options;
398 options.as_user = token;
399 EXPECT_TRUE(base::LaunchProcess(MakeCmdLine("SimpleChildProcess"),
400 options).IsValid());
403 static const char kEventToTriggerHandleSwitch[] = "event-to-trigger-handle";
405 MULTIPROCESS_TEST_MAIN(TriggerEventChildProcess) {
406 std::string handle_value_string =
407 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
408 kEventToTriggerHandleSwitch);
409 CHECK(!handle_value_string.empty());
411 uint64 handle_value_uint64;
412 CHECK(base::StringToUint64(handle_value_string, &handle_value_uint64));
413 // Give ownership of the handle to |event|.
414 base::WaitableEvent event(base::win::ScopedHandle(
415 reinterpret_cast<HANDLE>(handle_value_uint64)));
417 event.Signal();
419 return 0;
422 TEST_F(ProcessUtilTest, InheritSpecifiedHandles) {
423 // Manually create the event, so that it can be inheritable.
424 SECURITY_ATTRIBUTES security_attributes = {};
425 security_attributes.nLength = static_cast<DWORD>(sizeof(security_attributes));
426 security_attributes.lpSecurityDescriptor = NULL;
427 security_attributes.bInheritHandle = true;
429 // Takes ownership of the event handle.
430 base::WaitableEvent event(base::win::ScopedHandle(
431 CreateEvent(&security_attributes, true, false, NULL)));
432 base::HandlesToInheritVector handles_to_inherit;
433 handles_to_inherit.push_back(event.handle());
434 base::LaunchOptions options;
435 options.handles_to_inherit = &handles_to_inherit;
437 base::CommandLine cmd_line = MakeCmdLine("TriggerEventChildProcess");
438 cmd_line.AppendSwitchASCII(kEventToTriggerHandleSwitch,
439 base::Uint64ToString(reinterpret_cast<uint64>(event.handle())));
441 // This functionality actually requires Vista or later. Make sure that it
442 // fails properly on XP.
443 if (base::win::GetVersion() < base::win::VERSION_VISTA) {
444 EXPECT_FALSE(base::LaunchProcess(cmd_line, options).IsValid());
445 return;
448 // Launch the process and wait for it to trigger the event.
449 ASSERT_TRUE(base::LaunchProcess(cmd_line, options).IsValid());
450 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
452 #endif // defined(OS_WIN)
454 #if defined(OS_POSIX)
456 namespace {
458 // Returns the maximum number of files that a process can have open.
459 // Returns 0 on error.
460 int GetMaxFilesOpenInProcess() {
461 struct rlimit rlim;
462 if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
463 return 0;
466 // rlim_t is a uint64 - clip to maxint. We do this since FD #s are ints
467 // which are all 32 bits on the supported platforms.
468 rlim_t max_int = static_cast<rlim_t>(std::numeric_limits<int32>::max());
469 if (rlim.rlim_cur > max_int) {
470 return max_int;
473 return rlim.rlim_cur;
476 const int kChildPipe = 20; // FD # for write end of pipe in child process.
478 #if defined(OS_MACOSX)
480 // <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/sys/guarded.h>
481 #if !defined(_GUARDID_T)
482 #define _GUARDID_T
483 typedef __uint64_t guardid_t;
484 #endif // _GUARDID_T
486 // From .../MacOSX10.9.sdk/usr/include/sys/syscall.h
487 #if !defined(SYS_change_fdguard_np)
488 #define SYS_change_fdguard_np 444
489 #endif
491 // <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/sys/guarded.h>
492 #if !defined(GUARD_DUP)
493 #define GUARD_DUP (1u << 1)
494 #endif
496 // <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/kern/kern_guarded.c?txt>
498 // Atomically replaces |guard|/|guardflags| with |nguard|/|nguardflags| on |fd|.
499 int change_fdguard_np(int fd,
500 const guardid_t *guard, u_int guardflags,
501 const guardid_t *nguard, u_int nguardflags,
502 int *fdflagsp) {
503 return syscall(SYS_change_fdguard_np, fd, guard, guardflags,
504 nguard, nguardflags, fdflagsp);
507 // Attempt to set a file-descriptor guard on |fd|. In case of success, remove
508 // it and return |true| to indicate that it can be guarded. Returning |false|
509 // means either that |fd| is guarded by some other code, or more likely EBADF.
511 // Starting with 10.9, libdispatch began setting GUARD_DUP on a file descriptor.
512 // Unfortunately, it is spun up as part of +[NSApplication initialize], which is
513 // not really something that Chromium can avoid using on OSX. See
514 // <http://crbug.com/338157>. This function allows querying whether the file
515 // descriptor is guarded before attempting to close it.
516 bool CanGuardFd(int fd) {
517 // The syscall is first provided in 10.9/Mavericks.
518 if (!base::mac::IsOSMavericksOrLater())
519 return true;
521 // Saves the original flags to reset later.
522 int original_fdflags = 0;
524 // This can be any value at all, it just has to match up between the two
525 // calls.
526 const guardid_t kGuard = 15;
528 // Attempt to change the guard. This can fail with EBADF if the file
529 // descriptor is bad, or EINVAL if the fd already has a guard set.
530 int ret =
531 change_fdguard_np(fd, NULL, 0, &kGuard, GUARD_DUP, &original_fdflags);
532 if (ret == -1)
533 return false;
535 // Remove the guard. It should not be possible to fail in removing the guard
536 // just added.
537 ret = change_fdguard_np(fd, &kGuard, GUARD_DUP, NULL, 0, &original_fdflags);
538 DPCHECK(ret == 0);
540 return true;
542 #endif // OS_MACOSX
544 } // namespace
546 MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess) {
547 // This child process counts the number of open FDs, it then writes that
548 // number out to a pipe connected to the parent.
549 int num_open_files = 0;
550 int write_pipe = kChildPipe;
551 int max_files = GetMaxFilesOpenInProcess();
552 for (int i = STDERR_FILENO + 1; i < max_files; i++) {
553 #if defined(OS_MACOSX)
554 // Ignore guarded or invalid file descriptors.
555 if (!CanGuardFd(i))
556 continue;
557 #endif
559 if (i != kChildPipe) {
560 int fd;
561 if ((fd = HANDLE_EINTR(dup(i))) != -1) {
562 close(fd);
563 num_open_files += 1;
568 int written = HANDLE_EINTR(write(write_pipe, &num_open_files,
569 sizeof(num_open_files)));
570 DCHECK_EQ(static_cast<size_t>(written), sizeof(num_open_files));
571 int ret = IGNORE_EINTR(close(write_pipe));
572 DPCHECK(ret == 0);
574 return 0;
577 int ProcessUtilTest::CountOpenFDsInChild() {
578 int fds[2];
579 if (pipe(fds) < 0)
580 NOTREACHED();
582 base::FileHandleMappingVector fd_mapping_vec;
583 fd_mapping_vec.push_back(std::pair<int, int>(fds[1], kChildPipe));
584 base::LaunchOptions options;
585 options.fds_to_remap = &fd_mapping_vec;
586 base::Process process =
587 SpawnChildWithOptions("ProcessUtilsLeakFDChildProcess", options);
588 CHECK(process.IsValid());
589 int ret = IGNORE_EINTR(close(fds[1]));
590 DPCHECK(ret == 0);
592 // Read number of open files in client process from pipe;
593 int num_open_files = -1;
594 ssize_t bytes_read =
595 HANDLE_EINTR(read(fds[0], &num_open_files, sizeof(num_open_files)));
596 CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(num_open_files)));
598 #if defined(THREAD_SANITIZER)
599 // Compiler-based ThreadSanitizer makes this test slow.
600 base::TimeDelta timeout = base::TimeDelta::FromSeconds(3);
601 #else
602 base::TimeDelta timeout = base::TimeDelta::FromSeconds(1);
603 #endif
604 int exit_code;
605 CHECK(process.WaitForExitWithTimeout(timeout, &exit_code));
606 ret = IGNORE_EINTR(close(fds[0]));
607 DPCHECK(ret == 0);
609 return num_open_files;
612 #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
613 // ProcessUtilTest.FDRemapping is flaky when ran under xvfb-run on Precise.
614 // The problem is 100% reproducible with both ASan and TSan.
615 // See http://crbug.com/136720.
616 #define MAYBE_FDRemapping DISABLED_FDRemapping
617 #else
618 #define MAYBE_FDRemapping FDRemapping
619 #endif
620 TEST_F(ProcessUtilTest, MAYBE_FDRemapping) {
621 int fds_before = CountOpenFDsInChild();
623 // open some dummy fds to make sure they don't propagate over to the
624 // child process.
625 int dev_null = open("/dev/null", O_RDONLY);
626 int sockets[2];
627 socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
629 int fds_after = CountOpenFDsInChild();
631 ASSERT_EQ(fds_after, fds_before);
633 int ret;
634 ret = IGNORE_EINTR(close(sockets[0]));
635 DPCHECK(ret == 0);
636 ret = IGNORE_EINTR(close(sockets[1]));
637 DPCHECK(ret == 0);
638 ret = IGNORE_EINTR(close(dev_null));
639 DPCHECK(ret == 0);
642 namespace {
644 std::string TestLaunchProcess(const std::vector<std::string>& args,
645 const base::EnvironmentMap& env_changes,
646 const bool clear_environ,
647 const int clone_flags) {
648 base::FileHandleMappingVector fds_to_remap;
650 int fds[2];
651 PCHECK(pipe(fds) == 0);
653 fds_to_remap.push_back(std::make_pair(fds[1], 1));
654 base::LaunchOptions options;
655 options.wait = true;
656 options.environ = env_changes;
657 options.clear_environ = clear_environ;
658 options.fds_to_remap = &fds_to_remap;
659 #if defined(OS_LINUX)
660 options.clone_flags = clone_flags;
661 #else
662 CHECK_EQ(0, clone_flags);
663 #endif // OS_LINUX
664 EXPECT_TRUE(base::LaunchProcess(args, options).IsValid());
665 PCHECK(IGNORE_EINTR(close(fds[1])) == 0);
667 char buf[512];
668 const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
670 PCHECK(IGNORE_EINTR(close(fds[0])) == 0);
672 return std::string(buf, n);
675 const char kLargeString[] =
676 "0123456789012345678901234567890123456789012345678901234567890123456789"
677 "0123456789012345678901234567890123456789012345678901234567890123456789"
678 "0123456789012345678901234567890123456789012345678901234567890123456789"
679 "0123456789012345678901234567890123456789012345678901234567890123456789"
680 "0123456789012345678901234567890123456789012345678901234567890123456789"
681 "0123456789012345678901234567890123456789012345678901234567890123456789"
682 "0123456789012345678901234567890123456789012345678901234567890123456789";
684 } // namespace
686 TEST_F(ProcessUtilTest, LaunchProcess) {
687 base::EnvironmentMap env_changes;
688 std::vector<std::string> echo_base_test;
689 echo_base_test.push_back(kPosixShell);
690 echo_base_test.push_back("-c");
691 echo_base_test.push_back("echo $BASE_TEST");
693 std::vector<std::string> print_env;
694 print_env.push_back("/usr/bin/env");
695 const int no_clone_flags = 0;
696 const bool no_clear_environ = false;
698 const char kBaseTest[] = "BASE_TEST";
700 env_changes[kBaseTest] = "bar";
701 EXPECT_EQ("bar\n",
702 TestLaunchProcess(
703 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
704 env_changes.clear();
706 EXPECT_EQ(0, setenv(kBaseTest, "testing", 1 /* override */));
707 EXPECT_EQ("testing\n",
708 TestLaunchProcess(
709 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
711 env_changes[kBaseTest] = std::string();
712 EXPECT_EQ("\n",
713 TestLaunchProcess(
714 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
716 env_changes[kBaseTest] = "foo";
717 EXPECT_EQ("foo\n",
718 TestLaunchProcess(
719 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
721 env_changes.clear();
722 EXPECT_EQ(0, setenv(kBaseTest, kLargeString, 1 /* override */));
723 EXPECT_EQ(std::string(kLargeString) + "\n",
724 TestLaunchProcess(
725 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
727 env_changes[kBaseTest] = "wibble";
728 EXPECT_EQ("wibble\n",
729 TestLaunchProcess(
730 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
732 #if defined(OS_LINUX)
733 // Test a non-trival value for clone_flags.
734 // Don't test on Valgrind as it has limited support for clone().
735 if (!RunningOnValgrind()) {
736 EXPECT_EQ("wibble\n", TestLaunchProcess(echo_base_test, env_changes,
737 no_clear_environ, CLONE_FS));
740 EXPECT_EQ(
741 "BASE_TEST=wibble\n",
742 TestLaunchProcess(
743 print_env, env_changes, true /* clear_environ */, no_clone_flags));
744 env_changes.clear();
745 EXPECT_EQ(
747 TestLaunchProcess(
748 print_env, env_changes, true /* clear_environ */, no_clone_flags));
749 #endif
752 TEST_F(ProcessUtilTest, GetAppOutput) {
753 std::string output;
755 #if defined(OS_ANDROID)
756 std::vector<std::string> argv;
757 argv.push_back("sh"); // Instead of /bin/sh, force path search to find it.
758 argv.push_back("-c");
760 argv.push_back("exit 0");
761 EXPECT_TRUE(base::GetAppOutput(base::CommandLine(argv), &output));
762 EXPECT_STREQ("", output.c_str());
764 argv[2] = "exit 1";
765 EXPECT_FALSE(base::GetAppOutput(base::CommandLine(argv), &output));
766 EXPECT_STREQ("", output.c_str());
768 argv[2] = "echo foobar42";
769 EXPECT_TRUE(base::GetAppOutput(base::CommandLine(argv), &output));
770 EXPECT_STREQ("foobar42\n", output.c_str());
771 #else
772 EXPECT_TRUE(base::GetAppOutput(base::CommandLine(FilePath("true")),
773 &output));
774 EXPECT_STREQ("", output.c_str());
776 EXPECT_FALSE(base::GetAppOutput(base::CommandLine(FilePath("false")),
777 &output));
779 std::vector<std::string> argv;
780 argv.push_back("/bin/echo");
781 argv.push_back("-n");
782 argv.push_back("foobar42");
783 EXPECT_TRUE(base::GetAppOutput(base::CommandLine(argv), &output));
784 EXPECT_STREQ("foobar42", output.c_str());
785 #endif // defined(OS_ANDROID)
788 // Flakes on Android, crbug.com/375840
789 #if defined(OS_ANDROID)
790 #define MAYBE_GetAppOutputRestricted DISABLED_GetAppOutputRestricted
791 #else
792 #define MAYBE_GetAppOutputRestricted GetAppOutputRestricted
793 #endif
794 TEST_F(ProcessUtilTest, MAYBE_GetAppOutputRestricted) {
795 // Unfortunately, since we can't rely on the path, we need to know where
796 // everything is. So let's use /bin/sh, which is on every POSIX system, and
797 // its built-ins.
798 std::vector<std::string> argv;
799 argv.push_back(std::string(kShellPath)); // argv[0]
800 argv.push_back("-c"); // argv[1]
802 // On success, should set |output|. We use |/bin/sh -c 'exit 0'| instead of
803 // |true| since the location of the latter may be |/bin| or |/usr/bin| (and we
804 // need absolute paths).
805 argv.push_back("exit 0"); // argv[2]; equivalent to "true"
806 std::string output = "abc";
807 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
808 100));
809 EXPECT_STREQ("", output.c_str());
811 argv[2] = "exit 1"; // equivalent to "false"
812 output = "before";
813 EXPECT_FALSE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
814 100));
815 EXPECT_STREQ("", output.c_str());
817 // Amount of output exactly equal to space allowed.
818 argv[2] = "echo 123456789"; // (the sh built-in doesn't take "-n")
819 output.clear();
820 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
821 10));
822 EXPECT_STREQ("123456789\n", output.c_str());
824 // Amount of output greater than space allowed.
825 output.clear();
826 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
827 5));
828 EXPECT_STREQ("12345", output.c_str());
830 // Amount of output less than space allowed.
831 output.clear();
832 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
833 15));
834 EXPECT_STREQ("123456789\n", output.c_str());
836 // Zero space allowed.
837 output = "abc";
838 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
839 0));
840 EXPECT_STREQ("", output.c_str());
843 #if !defined(OS_MACOSX) && !defined(OS_OPENBSD)
844 // TODO(benwells): GetAppOutputRestricted should terminate applications
845 // with SIGPIPE when we have enough output. http://crbug.com/88502
846 TEST_F(ProcessUtilTest, GetAppOutputRestrictedSIGPIPE) {
847 std::vector<std::string> argv;
848 std::string output;
850 argv.push_back(std::string(kShellPath)); // argv[0]
851 argv.push_back("-c");
852 #if defined(OS_ANDROID)
853 argv.push_back("while echo 12345678901234567890; do :; done");
854 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
855 10));
856 EXPECT_STREQ("1234567890", output.c_str());
857 #else
858 argv.push_back("yes");
859 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
860 10));
861 EXPECT_STREQ("y\ny\ny\ny\ny\n", output.c_str());
862 #endif
864 #endif
866 #if defined(ADDRESS_SANITIZER) && defined(OS_MACOSX) && \
867 defined(ARCH_CPU_64_BITS)
868 // Times out under AddressSanitizer on 64-bit OS X, see
869 // http://crbug.com/298197.
870 #define MAYBE_GetAppOutputRestrictedNoZombies \
871 DISABLED_GetAppOutputRestrictedNoZombies
872 #else
873 #define MAYBE_GetAppOutputRestrictedNoZombies GetAppOutputRestrictedNoZombies
874 #endif
875 TEST_F(ProcessUtilTest, MAYBE_GetAppOutputRestrictedNoZombies) {
876 std::vector<std::string> argv;
878 argv.push_back(std::string(kShellPath)); // argv[0]
879 argv.push_back("-c"); // argv[1]
880 argv.push_back("echo 123456789012345678901234567890"); // argv[2]
882 // Run |GetAppOutputRestricted()| 300 (> default per-user processes on Mac OS
883 // 10.5) times with an output buffer big enough to capture all output.
884 for (int i = 0; i < 300; i++) {
885 std::string output;
886 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
887 100));
888 EXPECT_STREQ("123456789012345678901234567890\n", output.c_str());
891 // Ditto, but with an output buffer too small to capture all output.
892 for (int i = 0; i < 300; i++) {
893 std::string output;
894 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
895 10));
896 EXPECT_STREQ("1234567890", output.c_str());
900 TEST_F(ProcessUtilTest, GetAppOutputWithExitCode) {
901 // Test getting output from a successful application.
902 std::vector<std::string> argv;
903 std::string output;
904 int exit_code;
905 argv.push_back(std::string(kShellPath)); // argv[0]
906 argv.push_back("-c"); // argv[1]
907 argv.push_back("echo foo"); // argv[2];
908 EXPECT_TRUE(base::GetAppOutputWithExitCode(base::CommandLine(argv), &output,
909 &exit_code));
910 EXPECT_STREQ("foo\n", output.c_str());
911 EXPECT_EQ(exit_code, 0);
913 // Test getting output from an application which fails with a specific exit
914 // code.
915 output.clear();
916 argv[2] = "echo foo; exit 2";
917 EXPECT_TRUE(base::GetAppOutputWithExitCode(base::CommandLine(argv), &output,
918 &exit_code));
919 EXPECT_STREQ("foo\n", output.c_str());
920 EXPECT_EQ(exit_code, 2);
923 TEST_F(ProcessUtilTest, GetParentProcessId) {
924 base::ProcessId ppid = base::GetParentProcessId(base::GetCurrentProcId());
925 EXPECT_EQ(ppid, getppid());
928 // TODO(port): port those unit tests.
929 bool IsProcessDead(base::ProcessHandle child) {
930 // waitpid() will actually reap the process which is exactly NOT what we
931 // want to test for. The good thing is that if it can't find the process
932 // we'll get a nice value for errno which we can test for.
933 const pid_t result = HANDLE_EINTR(waitpid(child, NULL, WNOHANG));
934 return result == -1 && errno == ECHILD;
937 TEST_F(ProcessUtilTest, DelayedTermination) {
938 base::Process child_process = SpawnChild("process_util_test_never_die");
939 ASSERT_TRUE(child_process.IsValid());
940 base::EnsureProcessTerminated(child_process.Duplicate());
941 int exit_code;
942 child_process.WaitForExitWithTimeout(base::TimeDelta::FromSeconds(5),
943 &exit_code);
945 // Check that process was really killed.
946 EXPECT_TRUE(IsProcessDead(child_process.Handle()));
949 MULTIPROCESS_TEST_MAIN(process_util_test_never_die) {
950 while (1) {
951 sleep(500);
953 return 0;
956 TEST_F(ProcessUtilTest, ImmediateTermination) {
957 base::Process child_process = SpawnChild("process_util_test_die_immediately");
958 ASSERT_TRUE(child_process.IsValid());
959 // Give it time to die.
960 sleep(2);
961 base::EnsureProcessTerminated(child_process.Duplicate());
963 // Check that process was really killed.
964 EXPECT_TRUE(IsProcessDead(child_process.Handle()));
967 MULTIPROCESS_TEST_MAIN(process_util_test_die_immediately) {
968 return 0;
971 #if !defined(OS_ANDROID)
972 const char kPipeValue = '\xcc';
974 class ReadFromPipeDelegate : public base::LaunchOptions::PreExecDelegate {
975 public:
976 explicit ReadFromPipeDelegate(int fd) : fd_(fd) {}
977 ~ReadFromPipeDelegate() override {}
978 void RunAsyncSafe() override {
979 char c;
980 RAW_CHECK(HANDLE_EINTR(read(fd_, &c, 1)) == 1);
981 RAW_CHECK(IGNORE_EINTR(close(fd_)) == 0);
982 RAW_CHECK(c == kPipeValue);
985 private:
986 int fd_;
987 DISALLOW_COPY_AND_ASSIGN(ReadFromPipeDelegate);
990 TEST_F(ProcessUtilTest, PreExecHook) {
991 int pipe_fds[2];
992 ASSERT_EQ(0, pipe(pipe_fds));
994 base::ScopedFD read_fd(pipe_fds[0]);
995 base::ScopedFD write_fd(pipe_fds[1]);
996 base::FileHandleMappingVector fds_to_remap;
997 fds_to_remap.push_back(std::make_pair(read_fd.get(), read_fd.get()));
999 ReadFromPipeDelegate read_from_pipe_delegate(read_fd.get());
1000 base::LaunchOptions options;
1001 options.fds_to_remap = &fds_to_remap;
1002 options.pre_exec_delegate = &read_from_pipe_delegate;
1003 base::Process process(SpawnChildWithOptions("SimpleChildProcess", options));
1004 ASSERT_TRUE(process.IsValid());
1006 read_fd.reset();
1007 ASSERT_EQ(1, HANDLE_EINTR(write(write_fd.get(), &kPipeValue, 1)));
1009 int exit_code = 42;
1010 EXPECT_TRUE(process.WaitForExit(&exit_code));
1011 EXPECT_EQ(0, exit_code);
1013 #endif // !defined(OS_ANDROID)
1015 #endif // defined(OS_POSIX)
1017 #if defined(OS_LINUX)
1018 const int kSuccess = 0;
1020 MULTIPROCESS_TEST_MAIN(CheckPidProcess) {
1021 const pid_t kInitPid = 1;
1022 const pid_t pid = syscall(__NR_getpid);
1023 CHECK(pid == kInitPid);
1024 CHECK(getpid() == pid);
1025 return kSuccess;
1028 #if defined(CLONE_NEWUSER) && defined(CLONE_NEWPID)
1029 TEST_F(ProcessUtilTest, CloneFlags) {
1030 if (RunningOnValgrind() ||
1031 !base::PathExists(FilePath("/proc/self/ns/user")) ||
1032 !base::PathExists(FilePath("/proc/self/ns/pid"))) {
1033 // User or PID namespaces are not supported.
1034 return;
1037 base::LaunchOptions options;
1038 options.clone_flags = CLONE_NEWUSER | CLONE_NEWPID;
1040 base::Process process(SpawnChildWithOptions("CheckPidProcess", options));
1041 ASSERT_TRUE(process.IsValid());
1043 int exit_code = 42;
1044 EXPECT_TRUE(process.WaitForExit(&exit_code));
1045 EXPECT_EQ(kSuccess, exit_code);
1047 #endif
1049 TEST(ForkWithFlagsTest, UpdatesPidCache) {
1050 // The libc clone function, which allows ForkWithFlags to keep the pid cache
1051 // up to date, does not work on Valgrind.
1052 if (RunningOnValgrind()) {
1053 return;
1056 // Warm up the libc pid cache, if there is one.
1057 ASSERT_EQ(syscall(__NR_getpid), getpid());
1059 pid_t ctid = 0;
1060 const pid_t pid =
1061 base::ForkWithFlags(SIGCHLD | CLONE_CHILD_SETTID, nullptr, &ctid);
1062 if (pid == 0) {
1063 // In child. Check both the raw getpid syscall and the libc getpid wrapper
1064 // (which may rely on a pid cache).
1065 RAW_CHECK(syscall(__NR_getpid) == ctid);
1066 RAW_CHECK(getpid() == ctid);
1067 _exit(kSuccess);
1070 ASSERT_NE(-1, pid);
1071 int status = 42;
1072 ASSERT_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0)));
1073 ASSERT_TRUE(WIFEXITED(status));
1074 EXPECT_EQ(kSuccess, WEXITSTATUS(status));
1077 MULTIPROCESS_TEST_MAIN(CheckCwdProcess) {
1078 base::FilePath expected;
1079 CHECK(base::GetTempDir(&expected));
1080 base::FilePath actual;
1081 CHECK(base::GetCurrentDirectory(&actual));
1082 CHECK(actual == expected);
1083 return kSuccess;
1086 TEST_F(ProcessUtilTest, CurrentDirectory) {
1087 // TODO(rickyz): Add support for passing arguments to multiprocess children,
1088 // then create a special directory for this test.
1089 base::FilePath tmp_dir;
1090 ASSERT_TRUE(base::GetTempDir(&tmp_dir));
1092 base::LaunchOptions options;
1093 options.current_directory = tmp_dir;
1095 base::Process process(SpawnChildWithOptions("CheckCwdProcess", options));
1096 ASSERT_TRUE(process.IsValid());
1098 int exit_code = 42;
1099 EXPECT_TRUE(process.WaitForExit(&exit_code));
1100 EXPECT_EQ(kSuccess, exit_code);
1103 TEST_F(ProcessUtilTest, InvalidCurrentDirectory) {
1104 base::LaunchOptions options;
1105 options.current_directory = base::FilePath("/dev/null");
1107 base::Process process(SpawnChildWithOptions("SimpleChildProcess", options));
1108 ASSERT_TRUE(process.IsValid());
1110 int exit_code = kSuccess;
1111 EXPECT_TRUE(process.WaitForExit(&exit_code));
1112 EXPECT_NE(kSuccess, exit_code);
1114 #endif