blob: 1f7f1b2c776edcfe2942c7564a74a209942804ec [file] [log] [blame]
Daniel Eratb8cf9492015-07-06 13:18:13 -06001// 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/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"
35
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
63using base::FilePath;
64
65namespace {
66
67#if defined(OS_ANDROID)
68const char kShellPath[] = "/system/bin/sh";
69const char kPosixShell[] = "sh";
70#else
71const char kShellPath[] = "/bin/sh";
72const char kPosixShell[] = "bash";
73#endif
74
75const char kSignalFileSlow[] = "SlowChildProcess.die";
76const char kSignalFileKill[] = "KilledChildProcess.die";
77
78#if defined(OS_POSIX)
79const char kSignalFileTerm[] = "TerminatedChildProcess.die";
80#endif
81
82#if defined(OS_WIN)
83const int kExpectedStillRunningExitCode = 0x102;
84const int kExpectedKilledExitCode = 1;
85#else
86const int kExpectedStillRunningExitCode = 0;
87#endif
88
89// Sleeps until file filename is created.
90void 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);
97}
98
99// Signals children they should die now.
100void SignalChildren(const char* filename) {
101 FILE* fp = fopen(filename, "w");
102 fclose(fp);
103}
104
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.
110base::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());
122
123 return status;
124}
125
126} // namespace
127
128class 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);
137};
138
139std::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
148}
149
150MULTIPROCESS_TEST_MAIN(SimpleChildProcess) {
151 return 0;
152}
153
154// TODO(viettrungluu): This should be in a "MultiProcessTestTest".
155TEST_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));
161}
162
163MULTIPROCESS_TEST_MAIN(SlowChildProcess) {
164 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileSlow).c_str());
165 return 0;
166}
167
168TEST_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());
179}
180
181// Times out on Linux and Win, flakes on other platforms, http://crbug.com/95058
182TEST_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());
188
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);
193
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());
201}
202
203#if defined(OS_WIN)
204// TODO(cpu): figure out how to test this in other platforms.
205TEST_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);
213}
214#endif
215
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.
221//
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.
225const char kSignalFileCrash[] = "CrashingChildProcess.die";
226
227MULTIPROCESS_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;
238}
239
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
247TEST_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());
253
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);
258
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);
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
274 // Reset signal handlers back to "normal".
275 base::debug::EnableInProcessStackDumping();
276 remove(signal_file.c_str());
277}
278#endif // !defined(OS_MACOSX)
279
280MULTIPROCESS_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;
291}
292
293#if defined(OS_POSIX)
294MULTIPROCESS_TEST_MAIN(TerminatedChildProcess) {
295 WaitToDie(ProcessUtilTest::GetSignalFilePath(kSignalFileTerm).c_str());
296 // Send a SIGTERM to this process.
297 ::kill(getpid(), SIGTERM);
298 return 1;
299}
300#endif
301
302TEST_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());
308
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);
313
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
323
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());
333}
334
335#if defined(OS_POSIX)
336TEST_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());
342
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);
347
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);
353
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());
359}
360#endif
361
362#if defined(OS_WIN)
363// TODO(estade): if possible, port this test.
364TEST_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!";
370 }
371 // cmd.exe's echo always adds a \r\n to its output.
372 std::string expected(message);
373 expected += "\r\n";
374
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);
382
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);
391}
392
393// TODO(estade): if possible, port this test.
394TEST_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());
401}
402
403static const char kEventToTriggerHandleSwitch[] = "event-to-trigger-handle";
404
405MULTIPROCESS_TEST_MAIN(TriggerEventChildProcess) {
406 std::string handle_value_string =
407 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
408 kEventToTriggerHandleSwitch);
409 CHECK(!handle_value_string.empty());
410
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)));
416
417 event.Signal();
418
419 return 0;
420}
421
422TEST_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;
428
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;
436
437 base::CommandLine cmd_line = MakeCmdLine("TriggerEventChildProcess");
438 cmd_line.AppendSwitchASCII(kEventToTriggerHandleSwitch,
439 base::Uint64ToString(reinterpret_cast<uint64>(event.handle())));
440
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;
446 }
447
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()));
451}
452#endif // defined(OS_WIN)
453
454#if defined(OS_POSIX)
455
456namespace {
457
458// Returns the maximum number of files that a process can have open.
459// Returns 0 on error.
460int GetMaxFilesOpenInProcess() {
461 struct rlimit rlim;
462 if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
463 return 0;
464 }
465
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;
471 }
472
473 return rlim.rlim_cur;
474}
475
476const int kChildPipe = 20; // FD # for write end of pipe in child process.
477
478#if defined(OS_MACOSX)
479
480// <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/sys/guarded.h>
481#if !defined(_GUARDID_T)
482#define _GUARDID_T
483typedef __uint64_t guardid_t;
484#endif // _GUARDID_T
485
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
490
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
495
496// <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/kern/kern_guarded.c?txt>
497//
498// Atomically replaces |guard|/|guardflags| with |nguard|/|nguardflags| on |fd|.
499int 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);
505}
506
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.
510//
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.
516bool CanGuardFd(int fd) {
517 // The syscall is first provided in 10.9/Mavericks.
518 if (!base::mac::IsOSMavericksOrLater())
519 return true;
520
521 // Saves the original flags to reset later.
522 int original_fdflags = 0;
523
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;
527
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;
534
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);
539
540 return true;
541}
542#endif // OS_MACOSX
543
544} // namespace
545
546MULTIPROCESS_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
558
559 if (i != kChildPipe) {
560 int fd;
561 if ((fd = HANDLE_EINTR(dup(i))) != -1) {
562 close(fd);
563 num_open_files += 1;
564 }
565 }
566 }
567
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);
573
574 return 0;
575}
576
577int ProcessUtilTest::CountOpenFDsInChild() {
578 int fds[2];
579 if (pipe(fds) < 0)
580 NOTREACHED();
581
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);
591
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)));
597
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);
608
609 return num_open_files;
610}
611
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
620TEST_F(ProcessUtilTest, MAYBE_FDRemapping) {
621 int fds_before = CountOpenFDsInChild();
622
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);
628
629 int fds_after = CountOpenFDsInChild();
630
631 ASSERT_EQ(fds_after, fds_before);
632
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);
640}
641
642namespace {
643
644std::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;
649
650 int fds[2];
651 PCHECK(pipe(fds) == 0);
652
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);
666
667 char buf[512];
668 const ssize_t n = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
669
670 PCHECK(IGNORE_EINTR(close(fds[0])) == 0);
671
672 return std::string(buf, n);
673}
674
675const char kLargeString[] =
676 "0123456789012345678901234567890123456789012345678901234567890123456789"
677 "0123456789012345678901234567890123456789012345678901234567890123456789"
678 "0123456789012345678901234567890123456789012345678901234567890123456789"
679 "0123456789012345678901234567890123456789012345678901234567890123456789"
680 "0123456789012345678901234567890123456789012345678901234567890123456789"
681 "0123456789012345678901234567890123456789012345678901234567890123456789"
682 "0123456789012345678901234567890123456789012345678901234567890123456789";
683
684} // namespace
685
686TEST_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");
692
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;
697
698 const char kBaseTest[] = "BASE_TEST";
699
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();
705
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));
710
711 env_changes[kBaseTest] = std::string();
712 EXPECT_EQ("\n",
713 TestLaunchProcess(
714 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
715
716 env_changes[kBaseTest] = "foo";
717 EXPECT_EQ("foo\n",
718 TestLaunchProcess(
719 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
720
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));
726
727 env_changes[kBaseTest] = "wibble";
728 EXPECT_EQ("wibble\n",
729 TestLaunchProcess(
730 echo_base_test, env_changes, no_clear_environ, no_clone_flags));
731
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));
738 }
739
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(
746 "",
747 TestLaunchProcess(
748 print_env, env_changes, true /* clear_environ */, no_clone_flags));
749#endif
750}
751
752TEST_F(ProcessUtilTest, GetAppOutput) {
753 std::string output;
754
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");
759
760 argv.push_back("exit 0");
761 EXPECT_TRUE(base::GetAppOutput(base::CommandLine(argv), &output));
762 EXPECT_STREQ("", output.c_str());
763
764 argv[2] = "exit 1";
765 EXPECT_FALSE(base::GetAppOutput(base::CommandLine(argv), &output));
766 EXPECT_STREQ("", output.c_str());
767
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());
775
776 EXPECT_FALSE(base::GetAppOutput(base::CommandLine(FilePath("false")),
777 &output));
778
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)
786}
787
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
794TEST_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]
801
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());
810
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());
816
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());
823
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());
829
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());
835
836 // Zero space allowed.
837 output = "abc";
838 EXPECT_TRUE(base::GetAppOutputRestricted(base::CommandLine(argv), &output,
839 0));
840 EXPECT_STREQ("", output.c_str());
841}
842
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
846TEST_F(ProcessUtilTest, GetAppOutputRestrictedSIGPIPE) {
847 std::vector<std::string> argv;
848 std::string output;
849
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
863}
864#endif
865
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
875TEST_F(ProcessUtilTest, MAYBE_GetAppOutputRestrictedNoZombies) {
876 std::vector<std::string> argv;
877
878 argv.push_back(std::string(kShellPath)); // argv[0]
879 argv.push_back("-c"); // argv[1]
880 argv.push_back("echo 123456789012345678901234567890"); // argv[2]
881
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());
889 }
890
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());
897 }
898}
899
900TEST_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);
912
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);
921}
922
923TEST_F(ProcessUtilTest, GetParentProcessId) {
924 base::ProcessId ppid = base::GetParentProcessId(base::GetCurrentProcId());
925 EXPECT_EQ(ppid, getppid());
926}
927
928// TODO(port): port those unit tests.
929bool 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;
935}
936
937TEST_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);
944
945 // Check that process was really killed.
946 EXPECT_TRUE(IsProcessDead(child_process.Handle()));
947}
948
949MULTIPROCESS_TEST_MAIN(process_util_test_never_die) {
950 while (1) {
951 sleep(500);
952 }
953 return 0;
954}
955
956TEST_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());
962
963 // Check that process was really killed.
964 EXPECT_TRUE(IsProcessDead(child_process.Handle()));
965}
966
967MULTIPROCESS_TEST_MAIN(process_util_test_die_immediately) {
968 return 0;
969}
970
971#if !defined(OS_ANDROID)
972const char kPipeValue = '\xcc';
973
974class 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);
983 }
984
985 private:
986 int fd_;
987 DISALLOW_COPY_AND_ASSIGN(ReadFromPipeDelegate);
988};
989
990TEST_F(ProcessUtilTest, PreExecHook) {
991 int pipe_fds[2];
992 ASSERT_EQ(0, pipe(pipe_fds));
993
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()));
998
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());
1005
1006 read_fd.reset();
1007 ASSERT_EQ(1, HANDLE_EINTR(write(write_fd.get(), &kPipeValue, 1)));
1008
1009 int exit_code = 42;
1010 EXPECT_TRUE(process.WaitForExit(&exit_code));
1011 EXPECT_EQ(0, exit_code);
1012}
1013#endif // !defined(OS_ANDROID)
1014
1015#endif // defined(OS_POSIX)
1016
1017#if defined(OS_LINUX)
1018const int kSuccess = 0;
1019
1020MULTIPROCESS_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;
1026}
1027
1028TEST_F(ProcessUtilTest, CloneFlags) {
1029 if (RunningOnValgrind() ||
1030 !base::PathExists(FilePath("/proc/self/ns/user")) ||
1031 !base::PathExists(FilePath("/proc/self/ns/pid"))) {
1032 // User or PID namespaces are not supported.
1033 return;
1034 }
1035
1036 base::LaunchOptions options;
1037 options.clone_flags = CLONE_NEWUSER | CLONE_NEWPID;
1038
1039 base::Process process(SpawnChildWithOptions("CheckPidProcess", options));
1040 ASSERT_TRUE(process.IsValid());
1041
1042 int exit_code = 42;
1043 EXPECT_TRUE(process.WaitForExit(&exit_code));
1044 EXPECT_EQ(kSuccess, exit_code);
1045}
1046
1047TEST(ForkWithFlagsTest, UpdatesPidCache) {
1048 // The libc clone function, which allows ForkWithFlags to keep the pid cache
1049 // up to date, does not work on Valgrind.
1050 if (RunningOnValgrind()) {
1051 return;
1052 }
1053
1054 // Warm up the libc pid cache, if there is one.
1055 ASSERT_EQ(syscall(__NR_getpid), getpid());
1056
1057 pid_t ctid = 0;
1058 const pid_t pid =
1059 base::ForkWithFlags(SIGCHLD | CLONE_CHILD_SETTID, nullptr, &ctid);
1060 if (pid == 0) {
1061 // In child. Check both the raw getpid syscall and the libc getpid wrapper
1062 // (which may rely on a pid cache).
1063 RAW_CHECK(syscall(__NR_getpid) == ctid);
1064 RAW_CHECK(getpid() == ctid);
1065 _exit(kSuccess);
1066 }
1067
1068 ASSERT_NE(-1, pid);
1069 int status = 42;
1070 ASSERT_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0)));
1071 ASSERT_TRUE(WIFEXITED(status));
1072 EXPECT_EQ(kSuccess, WEXITSTATUS(status));
1073}
1074
1075MULTIPROCESS_TEST_MAIN(CheckCwdProcess) {
1076 base::FilePath expected;
1077 CHECK(base::GetTempDir(&expected));
1078 base::FilePath actual;
1079 CHECK(base::GetCurrentDirectory(&actual));
1080 CHECK(actual == expected);
1081 return kSuccess;
1082}
1083
1084TEST_F(ProcessUtilTest, CurrentDirectory) {
1085 // TODO(rickyz): Add support for passing arguments to multiprocess children,
1086 // then create a special directory for this test.
1087 base::FilePath tmp_dir;
1088 ASSERT_TRUE(base::GetTempDir(&tmp_dir));
1089
1090 base::LaunchOptions options;
1091 options.current_directory = tmp_dir;
1092
1093 base::Process process(SpawnChildWithOptions("CheckCwdProcess", options));
1094 ASSERT_TRUE(process.IsValid());
1095
1096 int exit_code = 42;
1097 EXPECT_TRUE(process.WaitForExit(&exit_code));
1098 EXPECT_EQ(kSuccess, exit_code);
1099}
1100
1101TEST_F(ProcessUtilTest, InvalidCurrentDirectory) {
1102 base::LaunchOptions options;
1103 options.current_directory = base::FilePath("/dev/null");
1104
1105 base::Process process(SpawnChildWithOptions("SimpleChildProcess", options));
1106 ASSERT_TRUE(process.IsValid());
1107
1108 int exit_code = kSuccess;
1109 EXPECT_TRUE(process.WaitForExit(&exit_code));
1110 EXPECT_NE(kSuccess, exit_code);
1111}
1112#endif