Revert "Fix broken channel icon in chrome://help on CrOS" and try again
[chromium-blink-merge.git] / base / process / process_util_unittest.cc
blob08144f2a18ec58789edd1cfdcbe988d411504cb4
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
62 #if defined(OS_ANDROID)
63 #include "third_party/lss/linux_syscall_support.h"
64 #endif
66 using base::FilePath;
68 namespace {
70 const char kSignalFileSlow[] = "SlowChildProcess.die";
71 const char kSignalFileKill[] = "KilledChildProcess.die";
73 #if defined(OS_POSIX)
74 const char kSignalFileTerm[] = "TerminatedChildProcess.die";
76 #if defined(OS_ANDROID)
77 const char kShellPath[] = "/system/bin/sh";
78 const char kPosixShell[] = "sh";
79 #else
80 const char kShellPath[] = "/bin/sh";
81 const char kPosixShell[] = "sh";
82 #endif
83 #endif // defined(OS_POSIX)
85 #if defined(OS_WIN)
86 const int kExpectedStillRunningExitCode = 0x102;
87 const int kExpectedKilledExitCode = 1;
88 #else
89 const int kExpectedStillRunningExitCode = 0;
90 #endif
92 // Sleeps until file filename is created.
93 void WaitToDie(const char* filename) {
94 FILE* fp;
95 do {
96 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
97 fp = fopen(filename, "r");
98 } while (!fp);
99 fclose(fp);
102 // Signals children they should die now.
103 void SignalChildren(const char* filename) {
104 FILE* fp = fopen(filename, "w");
105 fclose(fp);
108 // Using a pipe to the child to wait for an event was considered, but
109 // there were cases in the past where pipes caused problems (other
110 // libraries closing the fds, child deadlocking). This is a simple
111 // case, so it's not worth the risk. Using wait loops is discouraged
112 // in most instances.
113 base::TerminationStatus WaitForChildTermination(base::ProcessHandle handle,
114 int* exit_code) {
115 // Now we wait until the result is something other than STILL_RUNNING.
116 base::TerminationStatus status = base::TERMINATION_STATUS_STILL_RUNNING;
117 const base::TimeDelta kInterval = base::TimeDelta::FromMilliseconds(20);
118 base::TimeDelta waited;
119 do {
120 status = base::GetTerminationStatus(handle, exit_code);
121 base::PlatformThread::Sleep(kInterval);
122 waited += kInterval;
123 } while (status == base::TERMINATION_STATUS_STILL_RUNNING &&
124 waited < TestTimeouts::action_max_timeout());
126 return status;
129 } // namespace
131 class ProcessUtilTest : public base::MultiProcessTest {
132 public:
133 #if defined(OS_POSIX)
134 // Spawn a child process that counts how many file descriptors are open.
135 int CountOpenFDsInChild();
136 #endif
137 // Converts the filename to a platform specific filepath.
138 // On Android files can not be created in arbitrary directories.
139 static std::string GetSignalFilePath(const char* filename);
142 std::string ProcessUtilTest::GetSignalFilePath(const char* filename) {
143 #if !defined(OS_ANDROID)
144 return filename;
145 #else
146 FilePath tmp_dir;
147 PathService::Get(base::DIR_CACHE, &tmp_dir);
148 tmp_dir = tmp_dir.Append(filename);
149 return tmp_dir.value();
150 #endif
153 MULTIPROCESS_TEST_MAIN(SimpleChildProcess) {
154 return 0;
157 // TODO(viettrungluu): This should be in a "MultiProcessTestTest".
158 TEST_F(ProcessUtilTest, SpawnChild) {
159 base::Process process = SpawnChild("SimpleChildProcess");
160 ASSERT_TRUE(process.IsValid());
161 int exit_code;
162 EXPECT_TRUE(process.WaitForExitWithTimeout(
163 TestTimeouts::action_max_timeout(), &exit_code));
166 MULTIPROCESS_TEST_MAIN(SlowChildProcess) {
167 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileSlow).c_str());
168 return 0;
171 TEST_F(ProcessUtilTest, KillSlowChild) {
172 const std::string signal_file =
173 ProcessUtilTest::GetSignalFilePath(kSignalFileSlow);
174 remove(signal_file.c_str());
175 base::Process process = SpawnChild("SlowChildProcess");
176 ASSERT_TRUE(process.IsValid());
177 SignalChildren(signal_file.c_str());
178 int exit_code;
179 EXPECT_TRUE(process.WaitForExitWithTimeout(
180 TestTimeouts::action_max_timeout(), &exit_code));
181 remove(signal_file.c_str());
184 // Times out on Linux and Win, flakes on other platforms, http://crbug.com/95058
185 TEST_F(ProcessUtilTest, DISABLED_GetTerminationStatusExit) {
186 const std::string signal_file =
187 ProcessUtilTest::GetSignalFilePath(kSignalFileSlow);
188 remove(signal_file.c_str());
189 base::Process process = SpawnChild("SlowChildProcess");
190 ASSERT_TRUE(process.IsValid());
192 int exit_code = 42;
193 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
194 base::GetTerminationStatus(process.Handle(), &exit_code));
195 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
197 SignalChildren(signal_file.c_str());
198 exit_code = 42;
199 base::TerminationStatus status =
200 WaitForChildTermination(process.Handle(), &exit_code);
201 EXPECT_EQ(base::TERMINATION_STATUS_NORMAL_TERMINATION, status);
202 EXPECT_EQ(0, exit_code);
203 remove(signal_file.c_str());
206 #if defined(OS_WIN)
207 // TODO(cpu): figure out how to test this in other platforms.
208 TEST_F(ProcessUtilTest, GetProcId) {
209 base::ProcessId id1 = base::GetProcId(GetCurrentProcess());
210 EXPECT_NE(0ul, id1);
211 base::Process process = SpawnChild("SimpleChildProcess");
212 ASSERT_TRUE(process.IsValid());
213 base::ProcessId id2 = process.Pid();
214 EXPECT_NE(0ul, id2);
215 EXPECT_NE(id1, id2);
217 #endif
219 #if !defined(OS_MACOSX)
220 // This test is disabled on Mac, since it's flaky due to ReportCrash
221 // taking a variable amount of time to parse and load the debug and
222 // symbol data for this unit test's executable before firing the
223 // signal handler.
225 // TODO(gspencer): turn this test process into a very small program
226 // with no symbols (instead of using the multiprocess testing
227 // framework) to reduce the ReportCrash overhead.
228 const char kSignalFileCrash[] = "CrashingChildProcess.die";
230 MULTIPROCESS_TEST_MAIN(CrashingChildProcess) {
231 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileCrash).c_str());
232 #if defined(OS_ANDROID)
233 // Android L+ expose signal and sigaction symbols that override the system
234 // ones. There is a bug in these functions where a request to set the handler
235 // to SIG_DFL is ignored. In that case, an infinite loop is entered as the
236 // signal is repeatedly sent to the crash dump signal handler.
237 // To work around this, directly call the system's sigaction.
238 struct kernel_sigaction sa;
239 memset(&sa, 0, sizeof(sa));
240 sys_sigemptyset(&sa.sa_mask);
241 sa.sa_handler_ = SIG_DFL;
242 sa.sa_flags = SA_RESTART;
243 sys_rt_sigaction(SIGSEGV, &sa, NULL, sizeof(kernel_sigset_t));
244 #elif defined(OS_POSIX)
245 // Have to disable to signal handler for segv so we can get a crash
246 // instead of an abnormal termination through the crash dump handler.
247 ::signal(SIGSEGV, SIG_DFL);
248 #endif
249 // Make this process have a segmentation fault.
250 volatile int* oops = NULL;
251 *oops = 0xDEAD;
252 return 1;
255 // This test intentionally crashes, so we don't need to run it under
256 // AddressSanitizer.
257 #if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
258 #define MAYBE_GetTerminationStatusCrash DISABLED_GetTerminationStatusCrash
259 #else
260 #define MAYBE_GetTerminationStatusCrash GetTerminationStatusCrash
261 #endif
262 TEST_F(ProcessUtilTest, MAYBE_GetTerminationStatusCrash) {
263 const std::string signal_file =
264 ProcessUtilTest::GetSignalFilePath(kSignalFileCrash);
265 remove(signal_file.c_str());
266 base::Process process = SpawnChild("CrashingChildProcess");
267 ASSERT_TRUE(process.IsValid());
269 int exit_code = 42;
270 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
271 base::GetTerminationStatus(process.Handle(), &exit_code));
272 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
274 SignalChildren(signal_file.c_str());
275 exit_code = 42;
276 base::TerminationStatus status =
277 WaitForChildTermination(process.Handle(), &exit_code);
278 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_CRASHED, status);
280 #if defined(OS_WIN)
281 EXPECT_EQ(0xc0000005, exit_code);
282 #elif defined(OS_POSIX)
283 int signaled = WIFSIGNALED(exit_code);
284 EXPECT_NE(0, signaled);
285 int signal = WTERMSIG(exit_code);
286 EXPECT_EQ(SIGSEGV, signal);
287 #endif
289 // Reset signal handlers back to "normal".
290 base::debug::EnableInProcessStackDumping();
291 remove(signal_file.c_str());
293 #endif // !defined(OS_MACOSX)
295 MULTIPROCESS_TEST_MAIN(KilledChildProcess) {
296 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileKill).c_str());
297 #if defined(OS_WIN)
298 // Kill ourselves.
299 HANDLE handle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, ::GetCurrentProcessId());
300 ::TerminateProcess(handle, kExpectedKilledExitCode);
301 #elif defined(OS_POSIX)
302 // Send a SIGKILL to this process, just like the OOM killer would.
303 ::kill(getpid(), SIGKILL);
304 #endif
305 return 1;
308 #if defined(OS_POSIX)
309 MULTIPROCESS_TEST_MAIN(TerminatedChildProcess) {
310 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileTerm).c_str());
311 // Send a SIGTERM to this process.
312 ::kill(getpid(), SIGTERM);
313 return 1;
315 #endif
317 TEST_F(ProcessUtilTest, GetTerminationStatusSigKill) {
318 const std::string signal_file =
319 ProcessUtilTest::GetSignalFilePath(kSignalFileKill);
320 remove(signal_file.c_str());
321 base::Process process = SpawnChild("KilledChildProcess");
322 ASSERT_TRUE(process.IsValid());
324 int exit_code = 42;
325 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
326 base::GetTerminationStatus(process.Handle(), &exit_code));
327 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
329 SignalChildren(signal_file.c_str());
330 exit_code = 42;
331 base::TerminationStatus status =
332 WaitForChildTermination(process.Handle(), &exit_code);
333 #if defined(OS_CHROMEOS)
334 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM, status);
335 #else
336 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_WAS_KILLED, status);
337 #endif
339 #if defined(OS_WIN)
340 EXPECT_EQ(kExpectedKilledExitCode, exit_code);
341 #elif defined(OS_POSIX)
342 int signaled = WIFSIGNALED(exit_code);
343 EXPECT_NE(0, signaled);
344 int signal = WTERMSIG(exit_code);
345 EXPECT_EQ(SIGKILL, signal);
346 #endif
347 remove(signal_file.c_str());
350 #if defined(OS_POSIX)
351 TEST_F(ProcessUtilTest, GetTerminationStatusSigTerm) {
352 const std::string signal_file =
353 ProcessUtilTest::GetSignalFilePath(kSignalFileTerm);
354 remove(signal_file.c_str());
355 base::Process process = SpawnChild("TerminatedChildProcess");
356 ASSERT_TRUE(process.IsValid());
358 int exit_code = 42;
359 EXPECT_EQ(base::TERMINATION_STATUS_STILL_RUNNING,
360 base::GetTerminationStatus(process.Handle(), &exit_code));
361 EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
363 SignalChildren(signal_file.c_str());
364 exit_code = 42;
365 base::TerminationStatus status =
366 WaitForChildTermination(process.Handle(), &exit_code);
367 EXPECT_EQ(base::TERMINATION_STATUS_PROCESS_WAS_KILLED, status);
369 int signaled = WIFSIGNALED(exit_code);
370 EXPECT_NE(0, signaled);
371 int signal = WTERMSIG(exit_code);
372 EXPECT_EQ(SIGTERM, signal);
373 remove(signal_file.c_str());
375 #endif
377 #if defined(OS_WIN)
378 // TODO(estade): if possible, port this test.
379 TEST_F(ProcessUtilTest, GetAppOutput) {
380 // Let's create a decently long message.
381 std::string message;
382 for (int i = 0; i < 1025; i++) { // 1025 so it does not end on a kilo-byte
383 // boundary.
384 message += "Hello!";
386 // cmd.exe's echo always adds a \r\n to its output.
387 std::string expected(message);
388 expected += "\r\n";
390 FilePath cmd(L"cmd.exe");
391 base::CommandLine cmd_line(cmd);
392 cmd_line.AppendArg("/c");
393 cmd_line.AppendArg("echo " + message + "");
394 std::string output;
395 ASSERT_TRUE(base::GetAppOutput(cmd_line, &output));
396 EXPECT_EQ(expected, output);
398 // Let's make sure stderr is ignored.
399 base::CommandLine other_cmd_line(cmd);
400 other_cmd_line.AppendArg("/c");
401 // http://msdn.microsoft.com/library/cc772622.aspx
402 cmd_line.AppendArg("echo " + message + " >&2");
403 output.clear();
404 ASSERT_TRUE(base::GetAppOutput(other_cmd_line, &output));
405 EXPECT_EQ("", output);
408 // TODO(estade): if possible, port this test.
409 TEST_F(ProcessUtilTest, LaunchAsUser) {
410 base::UserTokenHandle token;
411 ASSERT_TRUE(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token));
412 base::LaunchOptions options;
413 options.as_user = token;
414 EXPECT_TRUE(base::LaunchProcess(MakeCmdLine("SimpleChildProcess"),
415 options).IsValid());
418 static const char kEventToTriggerHandleSwitch[] = "event-to-trigger-handle";
420 MULTIPROCESS_TEST_MAIN(TriggerEventChildProcess) {
421 std::string handle_value_string =
422 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
423 kEventToTriggerHandleSwitch);
424 CHECK(!handle_value_string.empty());
426 uint64 handle_value_uint64;
427 CHECK(base::StringToUint64(handle_value_string, &handle_value_uint64));
428 // Give ownership of the handle to |event|.
429 base::WaitableEvent event(base::win::ScopedHandle(
430 reinterpret_cast<HANDLE>(handle_value_uint64)));
432 event.Signal();
434 return 0;
437 TEST_F(ProcessUtilTest, InheritSpecifiedHandles) {
438 // Manually create the event, so that it can be inheritable.
439 SECURITY_ATTRIBUTES security_attributes = {};
440 security_attributes.nLength = static_cast<DWORD>(sizeof(security_attributes));
441 security_attributes.lpSecurityDescriptor = NULL;
442 security_attributes.bInheritHandle = true;
444 // Takes ownership of the event handle.
445 base::WaitableEvent event(base::win::ScopedHandle(
446 CreateEvent(&security_attributes, true, false, NULL)));
447 base::HandlesToInheritVector handles_to_inherit;
448 handles_to_inherit.push_back(event.handle());
449 base::LaunchOptions options;
450 options.handles_to_inherit = &handles_to_inherit;
452 base::CommandLine cmd_line = MakeCmdLine("TriggerEventChildProcess");
453 cmd_line.AppendSwitchASCII(kEventToTriggerHandleSwitch,
454 base::Uint64ToString(reinterpret_cast<uint64>(event.handle())));
456 // This functionality actually requires Vista or later. Make sure that it
457 // fails properly on XP.
458 if (base::win::GetVersion() < base::win::VERSION_VISTA) {
459 EXPECT_FALSE(base::LaunchProcess(cmd_line, options).IsValid());
460 return;
463 // Launch the process and wait for it to trigger the event.
464 ASSERT_TRUE(base::LaunchProcess(cmd_line, options).IsValid());
465 EXPECT_TRUE(event.TimedWait(TestTimeouts::action_max_timeout()));
467 #endif // defined(OS_WIN)
469 #if defined(OS_POSIX)
471 namespace {
473 // Returns the maximum number of files that a process can have open.
474 // Returns 0 on error.
475 int GetMaxFilesOpenInProcess() {
476 struct rlimit rlim;
477 if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
478 return 0;
481 // rlim_t is a uint64 - clip to maxint. We do this since FD #s are ints
482 // which are all 32 bits on the supported platforms.
483 rlim_t max_int = static_cast<rlim_t>(std::numeric_limits<int32>::max());
484 if (rlim.rlim_cur > max_int) {
485 return max_int;
488 return rlim.rlim_cur;
491 const int kChildPipe = 20; // FD # for write end of pipe in child process.
493 #if defined(OS_MACOSX)
495 // <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/sys/guarded.h>
496 #if !defined(_GUARDID_T)
497 #define _GUARDID_T
498 typedef __uint64_t guardid_t;
499 #endif // _GUARDID_T
501 // From .../MacOSX10.9.sdk/usr/include/sys/syscall.h
502 #if !defined(SYS_change_fdguard_np)
503 #define SYS_change_fdguard_np 444
504 #endif
506 // <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/sys/guarded.h>
507 #if !defined(GUARD_DUP)
508 #define GUARD_DUP (1u << 1)
509 #endif
511 // <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/kern/kern_guarded.c?txt>
513 // Atomically replaces |guard|/|guardflags| with |nguard|/|nguardflags| on |fd|.
514 int change_fdguard_np(int fd,
515 const guardid_t *guard, u_int guardflags,
516 const guardid_t *nguard, u_int nguardflags,
517 int *fdflagsp) {
518 return syscall(SYS_change_fdguard_np, fd, guard, guardflags,
519 nguard, nguardflags, fdflagsp);
522 // Attempt to set a file-descriptor guard on |fd|. In case of success, remove
523 // it and return |true| to indicate that it can be guarded. Returning |false|
524 // means either that |fd| is guarded by some other code, or more likely EBADF.
526 // Starting with 10.9, libdispatch began setting GUARD_DUP on a file descriptor.
527 // Unfortunately, it is spun up as part of +[NSApplication initialize], which is
528 // not really something that Chromium can avoid using on OSX. See
529 // <http://crbug.com/338157>. This function allows querying whether the file
530 // descriptor is guarded before attempting to close it.
531 bool CanGuardFd(int fd) {
532 // The syscall is first provided in 10.9/Mavericks.
533 if (!base::mac::IsOSMavericksOrLater())
534 return true;
536 // Saves the original flags to reset later.
537 int original_fdflags = 0;
539 // This can be any value at all, it just has to match up between the two
540 // calls.
541 const guardid_t kGuard = 15;
543 // Attempt to change the guard. This can fail with EBADF if the file
544 // descriptor is bad, or EINVAL if the fd already has a guard set.
545 int ret =
546 change_fdguard_np(fd, NULL, 0, &kGuard, GUARD_DUP, &original_fdflags);
547 if (ret == -1)
548 return false;
550 // Remove the guard. It should not be possible to fail in removing the guard
551 // just added.
552 ret = change_fdguard_np(fd, &kGuard, GUARD_DUP, NULL, 0, &original_fdflags);
553 DPCHECK(ret == 0);
555 return true;
557 #endif // OS_MACOSX
559 } // namespace
561 MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess) {
562 // This child process counts the number of open FDs, it then writes that
563 // number out to a pipe connected to the parent.
564 int num_open_files = 0;
565 int write_pipe = kChildPipe;
566 int max_files = GetMaxFilesOpenInProcess();
567 for (int i = STDERR_FILENO + 1; i < max_files; i++) {
568 #if defined(OS_MACOSX)
569 // Ignore guarded or invalid file descriptors.
570 if (!CanGuardFd(i))
571 continue;
572 #endif
574 if (i != kChildPipe) {
575 int fd;
576 if ((fd = HANDLE_EINTR(dup(i))) != -1) {
577 close(fd);
578 num_open_files += 1;
583 int written = HANDLE_EINTR(write(write_pipe, &num_open_files,
584 sizeof(num_open_files)));
585 DCHECK_EQ(static_cast<size_t>(written), sizeof(num_open_files));
586 int ret = IGNORE_EINTR(close(write_pipe));
587 DPCHECK(ret == 0);
589 return 0;
592 int ProcessUtilTest::CountOpenFDsInChild() {
593 int fds[2];
594 if (pipe(fds) < 0)
595 NOTREACHED();
597 base::FileHandleMappingVector fd_mapping_vec;
598 fd_mapping_vec.push_back(std::pair<int, int>(fds[1], kChildPipe));
599 base::LaunchOptions options;
600 options.fds_to_remap = &fd_mapping_vec;
601 base::Process process =
602 SpawnChildWithOptions("ProcessUtilsLeakFDChildProcess", options);
603 CHECK(process.IsValid());
604 int ret = IGNORE_EINTR(close(fds[1]));
605 DPCHECK(ret == 0);
607 // Read number of open files in client process from pipe;
608 int num_open_files = -1;
609 ssize_t bytes_read =
610 HANDLE_EINTR(read(fds[0], &num_open_files, sizeof(num_open_files)));
611 CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(num_open_files)));
613 #if defined(THREAD_SANITIZER)
614 // Compiler-based ThreadSanitizer makes this test slow.
615 base::TimeDelta timeout = base::TimeDelta::FromSeconds(3);
616 #else
617 base::TimeDelta timeout = base::TimeDelta::FromSeconds(1);
618 #endif
619 int exit_code;
620 CHECK(process.WaitForExitWithTimeout(timeout, &exit_code));
621 ret = IGNORE_EINTR(close(fds[0]));
622 DPCHECK(ret == 0);
624 return num_open_files;
627 #if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
628 // ProcessUtilTest.FDRemapping is flaky when ran under xvfb-run on Precise.
629 // The problem is 100% reproducible with both ASan and TSan.
630 // See http://crbug.com/136720.
631 #define MAYBE_FDRemapping DISABLED_FDRemapping
632 #else
633 #define MAYBE_FDRemapping FDRemapping
634 #endif
635 TEST_F(ProcessUtilTest, MAYBE_FDRemapping) {
636 int fds_before = CountOpenFDsInChild();
638 // open some dummy fds to make sure they don't propagate over to the
639 // child process.
640 int dev_null = open("/dev/null", O_RDONLY);
641 int sockets[2];
642 socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
644 int fds_after = CountOpenFDsInChild();
646 ASSERT_EQ(fds_after, fds_before);
648 int ret;
649 ret = IGNORE_EINTR(close(sockets[0]));
650 DPCHECK(ret == 0);
651 ret = IGNORE_EINTR(close(sockets[1]));
652 DPCHECK(ret == 0);
653 ret = IGNORE_EINTR(close(dev_null));
654 DPCHECK(ret == 0);
657 namespace {
659 std::string TestLaunchProcess(const std::vector<std::string>& args,
660 const base::EnvironmentMap& env_changes,
661 const bool clear_environ,
662 const int clone_flags) {
663 base::FileHandleMappingVector fds_to_remap;
665 int fds[2];
666 PCHECK(pipe(fds) == 0);
668 fds_to_remap.push_back(std::make_pair(fds[1], 1));
669 base::LaunchOptions options;
670 options.wait = true;
671 options.environ = env_changes;
672 options.clear_environ = clear_environ;
673 options.fds_to_remap = &fds_to_remap;
674 #if defined(OS_LINUX)
675 options.clone_flags = clone_flags;
676 #else
677 CHECK_EQ(0, clone_flags);
678 #endif // OS_LINUX
679 EXPECT_TRUE(base::LaunchProcess(args, options).IsValid());
680 PCHECK(IGNORE_EINTR(close(fds[1])) == 0);
682 char buf[512];
683 const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
685 PCHECK(IGNORE_EINTR(close(fds[0])) == 0);
687 return std::string(buf, n);
690 const char kLargeString[] =
691 "0123456789012345678901234567890123456789012345678901234567890123456789"
692 "0123456789012345678901234567890123456789012345678901234567890123456789"
693 "0123456789012345678901234567890123456789012345678901234567890123456789"
694 "0123456789012345678901234567890123456789012345678901234567890123456789"
695 "0123456789012345678901234567890123456789012345678901234567890123456789"
696 "0123456789012345678901234567890123456789012345678901234567890123456789"
697 "0123456789012345678901234567890123456789012345678901234567890123456789";
699 } // namespace
701 TEST_F(ProcessUtilTest, LaunchProcess) {
702 base::EnvironmentMap env_changes;
703 std::vector<std::string> echo_base_test;
704 echo_base_test.push_back(kPosixShell);
705 echo_base_test.push_back("-c");
706 echo_base_test.push_back("echo $BASE_TEST");
708 std::vector<std::string> print_env;
709 print_env.push_back("/usr/bin/env");
710 const int no_clone_flags = 0;
711 const bool no_clear_environ = false;
713 const char kBaseTest[] = "BASE_TEST";
715 env_changes[kBaseTest] = "bar";
716 EXPECT_EQ("bar\n",
717 TestLaunchProcess(
718 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
719 env_changes.clear();
721 EXPECT_EQ(0, setenv(kBaseTest, "testing", 1 /* override */));
722 EXPECT_EQ("testing\n",
723 TestLaunchProcess(
724 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
726 env_changes[kBaseTest] = std::string();
727 EXPECT_EQ("\n",
728 TestLaunchProcess(
729 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
731 env_changes[kBaseTest] = "foo";
732 EXPECT_EQ("foo\n",
733 TestLaunchProcess(
734 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
736 env_changes.clear();
737 EXPECT_EQ(0, setenv(kBaseTest, kLargeString, 1 /* override */));
738 EXPECT_EQ(std::string(kLargeString) + "\n",
739 TestLaunchProcess(
740 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
742 env_changes[kBaseTest] = "wibble";
743 EXPECT_EQ("wibble\n",
744 TestLaunchProcess(
745 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
747 #if defined(OS_LINUX)
748 // Test a non-trival value for clone_flags.
749 // Don't test on Valgrind as it has limited support for clone().
750 if (!RunningOnValgrind()) {
751 EXPECT_EQ("wibble\n", TestLaunchProcess(echo_base_test, env_changes,
752 no_clear_environ, CLONE_FS));
755 EXPECT_EQ(
756 "BASE_TEST=wibble\n",
757 TestLaunchProcess(
758 print_env, env_changes, true /* clear_environ */, no_clone_flags));
759 env_changes.clear();
760 EXPECT_EQ(
762 TestLaunchProcess(
763 print_env, env_changes, true /* clear_environ */, no_clone_flags));
764 #endif
767 TEST_F(ProcessUtilTest, GetAppOutput) {
768 std::string output;
770 #if defined(OS_ANDROID)
771 std::vector<std::string> argv;
772 argv.push_back("sh"); // Instead of /bin/sh, force path search to find it.
773 argv.push_back("-c");
775 argv.push_back("exit 0");
776 EXPECT_TRUE(base::GetAppOutput(base::CommandLine(argv), &output));
777 EXPECT_STREQ("", output.c_str());
779 argv[2] = "exit 1";
780 EXPECT_FALSE(base::GetAppOutput(base::CommandLine(argv), &output));
781 EXPECT_STREQ("", output.c_str());
783 argv[2] = "echo foobar42";
784 EXPECT_TRUE(base::GetAppOutput(base::CommandLine(argv), &output));
785 EXPECT_STREQ("foobar42\n", output.c_str());
786 #else
787 EXPECT_TRUE(base::GetAppOutput(base::CommandLine(FilePath("true")),
788 &output));
789 EXPECT_STREQ("", output.c_str());
791 EXPECT_FALSE(base::GetAppOutput(base::CommandLine(FilePath("false")),
792 &output));
794 std::vector<std::string> argv;
795 argv.push_back("/bin/echo");
796 argv.push_back("-n");
797 argv.push_back("foobar42");
798 EXPECT_TRUE(base::GetAppOutput(base::CommandLine(argv), &output));
799 EXPECT_STREQ("foobar42", output.c_str());
800 #endif // defined(OS_ANDROID)
803 // Flakes on Android, crbug.com/375840
804 #if defined(OS_ANDROID)
805 #define MAYBE_GetAppOutputRestricted DISABLED_GetAppOutputRestricted
806 #else
807 #define MAYBE_GetAppOutputRestricted GetAppOutputRestricted
808 #endif
809 TEST_F(ProcessUtilTest, MAYBE_GetAppOutputRestricted) {
810 // Unfortunately, since we can't rely on the path, we need to know where
811 // everything is. So let's use /bin/sh, which is on every POSIX system, and
812 // its built-ins.
813 std::vector<std::string> argv;
814 argv.push_back(std::string(kShellPath)); // argv[0]
815 argv.push_back("-c"); // argv[1]
817 // On success, should set |output|. We use |/bin/sh -c 'exit 0'| instead of
818 // |true| since the location of the latter may be |/bin| or |/usr/bin| (and we
819 // need absolute paths).
820 argv.push_back("exit 0"); // argv[2]; equivalent to "true"
821 std::string output = "abc";
822 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
823 100));
824 EXPECT_STREQ("", output.c_str());
826 argv[2] = "exit 1"; // equivalent to "false"
827 output = "before";
828 EXPECT_FALSE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
829 100));
830 EXPECT_STREQ("", output.c_str());
832 // Amount of output exactly equal to space allowed.
833 argv[2] = "echo 123456789"; // (the sh built-in doesn't take "-n")
834 output.clear();
835 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
836 10));
837 EXPECT_STREQ("123456789\n", output.c_str());
839 // Amount of output greater than space allowed.
840 output.clear();
841 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
842 5));
843 EXPECT_STREQ("12345", output.c_str());
845 // Amount of output less than space allowed.
846 output.clear();
847 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
848 15));
849 EXPECT_STREQ("123456789\n", output.c_str());
851 // Zero space allowed.
852 output = "abc";
853 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
854 0));
855 EXPECT_STREQ("", output.c_str());
858 #if !defined(OS_MACOSX) && !defined(OS_OPENBSD)
859 // TODO(benwells): GetAppOutputRestricted should terminate applications
860 // with SIGPIPE when we have enough output. http://crbug.com/88502
861 TEST_F(ProcessUtilTest, GetAppOutputRestrictedSIGPIPE) {
862 std::vector<std::string> argv;
863 std::string output;
865 argv.push_back(std::string(kShellPath)); // argv[0]
866 argv.push_back("-c");
867 #if defined(OS_ANDROID)
868 argv.push_back("while echo 12345678901234567890; do :; done");
869 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
870 10));
871 EXPECT_STREQ("1234567890", output.c_str());
872 #else
873 argv.push_back("yes");
874 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
875 10));
876 EXPECT_STREQ("y\ny\ny\ny\ny\n", output.c_str());
877 #endif
879 #endif
881 #if defined(ADDRESS_SANITIZER) && defined(OS_MACOSX) && \
882 defined(ARCH_CPU_64_BITS)
883 // Times out under AddressSanitizer on 64-bit OS X, see
884 // http://crbug.com/298197.
885 #define MAYBE_GetAppOutputRestrictedNoZombies \
886 DISABLED_GetAppOutputRestrictedNoZombies
887 #else
888 #define MAYBE_GetAppOutputRestrictedNoZombies GetAppOutputRestrictedNoZombies
889 #endif
890 TEST_F(ProcessUtilTest, MAYBE_GetAppOutputRestrictedNoZombies) {
891 std::vector<std::string> argv;
893 argv.push_back(std::string(kShellPath)); // argv[0]
894 argv.push_back("-c"); // argv[1]
895 argv.push_back("echo 123456789012345678901234567890"); // argv[2]
897 // Run |GetAppOutputRestricted()| 300 (> default per-user processes on Mac OS
898 // 10.5) times with an output buffer big enough to capture all output.
899 for (int i = 0; i < 300; i++) {
900 std::string output;
901 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
902 100));
903 EXPECT_STREQ("123456789012345678901234567890\n", output.c_str());
906 // Ditto, but with an output buffer too small to capture all output.
907 for (int i = 0; i < 300; i++) {
908 std::string output;
909 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
910 10));
911 EXPECT_STREQ("1234567890", output.c_str());
915 TEST_F(ProcessUtilTest, GetAppOutputWithExitCode) {
916 // Test getting output from a successful application.
917 std::vector<std::string> argv;
918 std::string output;
919 int exit_code;
920 argv.push_back(std::string(kShellPath)); // argv[0]
921 argv.push_back("-c"); // argv[1]
922 argv.push_back("echo foo"); // argv[2];
923 EXPECT_TRUE(base::GetAppOutputWithExitCode(base::CommandLine(argv), &output,
924 &exit_code));
925 EXPECT_STREQ("foo\n", output.c_str());
926 EXPECT_EQ(exit_code, 0);
928 // Test getting output from an application which fails with a specific exit
929 // code.
930 output.clear();
931 argv[2] = "echo foo; exit 2";
932 EXPECT_TRUE(base::GetAppOutputWithExitCode(base::CommandLine(argv), &output,
933 &exit_code));
934 EXPECT_STREQ("foo\n", output.c_str());
935 EXPECT_EQ(exit_code, 2);
938 TEST_F(ProcessUtilTest, GetParentProcessId) {
939 base::ProcessId ppid = base::GetParentProcessId(base::GetCurrentProcId());
940 EXPECT_EQ(ppid, getppid());
943 // TODO(port): port those unit tests.
944 bool IsProcessDead(base::ProcessHandle child) {
945 // waitpid() will actually reap the process which is exactly NOT what we
946 // want to test for. The good thing is that if it can't find the process
947 // we'll get a nice value for errno which we can test for.
948 const pid_t result = HANDLE_EINTR(waitpid(child, NULL, WNOHANG));
949 return result == -1 && errno == ECHILD;
952 TEST_F(ProcessUtilTest, DelayedTermination) {
953 base::Process child_process = SpawnChild("process_util_test_never_die");
954 ASSERT_TRUE(child_process.IsValid());
955 base::EnsureProcessTerminated(child_process.Duplicate());
956 int exit_code;
957 child_process.WaitForExitWithTimeout(base::TimeDelta::FromSeconds(5),
958 &exit_code);
960 // Check that process was really killed.
961 EXPECT_TRUE(IsProcessDead(child_process.Handle()));
964 MULTIPROCESS_TEST_MAIN(process_util_test_never_die) {
965 while (1) {
966 sleep(500);
968 return 0;
971 TEST_F(ProcessUtilTest, ImmediateTermination) {
972 base::Process child_process = SpawnChild("process_util_test_die_immediately");
973 ASSERT_TRUE(child_process.IsValid());
974 // Give it time to die.
975 sleep(2);
976 base::EnsureProcessTerminated(child_process.Duplicate());
978 // Check that process was really killed.
979 EXPECT_TRUE(IsProcessDead(child_process.Handle()));
982 MULTIPROCESS_TEST_MAIN(process_util_test_die_immediately) {
983 return 0;
986 #if !defined(OS_ANDROID)
987 const char kPipeValue = '\xcc';
989 class ReadFromPipeDelegate : public base::LaunchOptions::PreExecDelegate {
990 public:
991 explicit ReadFromPipeDelegate(int fd) : fd_(fd) {}
992 ~ReadFromPipeDelegate() override {}
993 void RunAsyncSafe() override {
994 char c;
995 RAW_CHECK(HANDLE_EINTR(read(fd_, &c, 1)) == 1);
996 RAW_CHECK(IGNORE_EINTR(close(fd_)) == 0);
997 RAW_CHECK(c == kPipeValue);
1000 private:
1001 int fd_;
1002 DISALLOW_COPY_AND_ASSIGN(ReadFromPipeDelegate);
1005 TEST_F(ProcessUtilTest, PreExecHook) {
1006 int pipe_fds[2];
1007 ASSERT_EQ(0, pipe(pipe_fds));
1009 base::ScopedFD read_fd(pipe_fds[0]);
1010 base::ScopedFD write_fd(pipe_fds[1]);
1011 base::FileHandleMappingVector fds_to_remap;
1012 fds_to_remap.push_back(std::make_pair(read_fd.get(), read_fd.get()));
1014 ReadFromPipeDelegate read_from_pipe_delegate(read_fd.get());
1015 base::LaunchOptions options;
1016 options.fds_to_remap = &fds_to_remap;
1017 options.pre_exec_delegate = &read_from_pipe_delegate;
1018 base::Process process(SpawnChildWithOptions("SimpleChildProcess", options));
1019 ASSERT_TRUE(process.IsValid());
1021 read_fd.reset();
1022 ASSERT_EQ(1, HANDLE_EINTR(write(write_fd.get(), &kPipeValue, 1)));
1024 int exit_code = 42;
1025 EXPECT_TRUE(process.WaitForExit(&exit_code));
1026 EXPECT_EQ(0, exit_code);
1028 #endif // !defined(OS_ANDROID)
1030 #endif // defined(OS_POSIX)
1032 #if defined(OS_LINUX)
1033 const int kSuccess = 0;
1035 MULTIPROCESS_TEST_MAIN(CheckPidProcess) {
1036 const pid_t kInitPid = 1;
1037 const pid_t pid = syscall(__NR_getpid);
1038 CHECK(pid == kInitPid);
1039 CHECK(getpid() == pid);
1040 return kSuccess;
1043 #if defined(CLONE_NEWUSER) && defined(CLONE_NEWPID)
1044 TEST_F(ProcessUtilTest, CloneFlags) {
1045 if (RunningOnValgrind() ||
1046 !base::PathExists(FilePath("/proc/self/ns/user")) ||
1047 !base::PathExists(FilePath("/proc/self/ns/pid"))) {
1048 // User or PID namespaces are not supported.
1049 return;
1052 base::LaunchOptions options;
1053 options.clone_flags = CLONE_NEWUSER | CLONE_NEWPID;
1055 base::Process process(SpawnChildWithOptions("CheckPidProcess", options));
1056 ASSERT_TRUE(process.IsValid());
1058 int exit_code = 42;
1059 EXPECT_TRUE(process.WaitForExit(&exit_code));
1060 EXPECT_EQ(kSuccess, exit_code);
1062 #endif
1064 TEST(ForkWithFlagsTest, UpdatesPidCache) {
1065 // The libc clone function, which allows ForkWithFlags to keep the pid cache
1066 // up to date, does not work on Valgrind.
1067 if (RunningOnValgrind()) {
1068 return;
1071 // Warm up the libc pid cache, if there is one.
1072 ASSERT_EQ(syscall(__NR_getpid), getpid());
1074 pid_t ctid = 0;
1075 const pid_t pid =
1076 base::ForkWithFlags(SIGCHLD | CLONE_CHILD_SETTID, nullptr, &ctid);
1077 if (pid == 0) {
1078 // In child. Check both the raw getpid syscall and the libc getpid wrapper
1079 // (which may rely on a pid cache).
1080 RAW_CHECK(syscall(__NR_getpid) == ctid);
1081 RAW_CHECK(getpid() == ctid);
1082 _exit(kSuccess);
1085 ASSERT_NE(-1, pid);
1086 int status = 42;
1087 ASSERT_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0)));
1088 ASSERT_TRUE(WIFEXITED(status));
1089 EXPECT_EQ(kSuccess, WEXITSTATUS(status));
1092 MULTIPROCESS_TEST_MAIN(CheckCwdProcess) {
1093 base::FilePath expected;
1094 CHECK(base::GetTempDir(&expected));
1095 base::FilePath actual;
1096 CHECK(base::GetCurrentDirectory(&actual));
1097 CHECK(actual == expected);
1098 return kSuccess;
1101 TEST_F(ProcessUtilTest, CurrentDirectory) {
1102 // TODO(rickyz): Add support for passing arguments to multiprocess children,
1103 // then create a special directory for this test.
1104 base::FilePath tmp_dir;
1105 ASSERT_TRUE(base::GetTempDir(&tmp_dir));
1107 base::LaunchOptions options;
1108 options.current_directory = tmp_dir;
1110 base::Process process(SpawnChildWithOptions("CheckCwdProcess", options));
1111 ASSERT_TRUE(process.IsValid());
1113 int exit_code = 42;
1114 EXPECT_TRUE(process.WaitForExit(&exit_code));
1115 EXPECT_EQ(kSuccess, exit_code);
1118 TEST_F(ProcessUtilTest, InvalidCurrentDirectory) {
1119 base::LaunchOptions options;
1120 options.current_directory = base::FilePath("/dev/null");
1122 base::Process process(SpawnChildWithOptions("SimpleChildProcess", options));
1123 ASSERT_TRUE(process.IsValid());
1125 int exit_code = kSuccess;
1126 EXPECT_TRUE(process.WaitForExit(&exit_code));
1127 EXPECT_NE(kSuccess, exit_code);
1129 #endif