| OLD | NEW | 
|    1 // Copyright 2014 The Chromium Authors. All rights reserved. |    1 // Copyright 2014 The Chromium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "base/process/process.h" |    5 #include "base/process/process.h" | 
|    6  |    6  | 
|    7 #include "base/files/file_path.h" |  | 
|    8 #include "base/files/file_util.h" |  | 
|    9 #include "base/files/scoped_file.h" |  | 
|   10 #include "base/posix/eintr_wrapper.h" |  | 
|   11 #include "base/process/kill.h" |    7 #include "base/process/kill.h" | 
|   12 #include "base/test/multiprocess_test.h" |    8 #include "base/test/multiprocess_test.h" | 
|   13 #include "base/test/test_timeouts.h" |    9 #include "base/test/test_timeouts.h" | 
|   14 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |  | 
|   15 #include "base/threading/platform_thread.h" |   10 #include "base/threading/platform_thread.h" | 
|   16 #include "build/build_config.h" |  | 
|   17 #include "testing/gtest/include/gtest/gtest.h" |   11 #include "testing/gtest/include/gtest/gtest.h" | 
|   18 #include "testing/multiprocess_func_list.h" |   12 #include "testing/multiprocess_func_list.h" | 
|   19  |   13  | 
|   20 #if defined(OS_LINUX) |  | 
|   21 #include <errno.h> |  | 
|   22 #include <sched.h> |  | 
|   23 #include <sys/syscall.h> |  | 
|   24 #include <sys/types.h> |  | 
|   25 #include <sys/wait.h> |  | 
|   26 #include <unistd.h> |  | 
|   27 #endif |  | 
|   28  |  | 
|   29 namespace { |   14 namespace { | 
|   30  |   15  | 
|   31 #if defined(OS_WIN) |   16 #if defined(OS_WIN) | 
|   32 const int kExpectedStillRunningExitCode = 0x102; |   17 const int kExpectedStillRunningExitCode = 0x102; | 
|   33 #else |   18 #else | 
|   34 const int kExpectedStillRunningExitCode = 0; |   19 const int kExpectedStillRunningExitCode = 0; | 
|   35 #endif |   20 #endif | 
|   36  |   21  | 
|   37 }  // namespace |   22 }  // namespace | 
|   38  |   23  | 
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  208   EXPECT_TRUE(process.SetProcessBackgrounded(false)); |  193   EXPECT_TRUE(process.SetProcessBackgrounded(false)); | 
|  209   EXPECT_FALSE(process.IsProcessBackgrounded()); |  194   EXPECT_FALSE(process.IsProcessBackgrounded()); | 
|  210 #else |  195 #else | 
|  211   process.SetProcessBackgrounded(true); |  196   process.SetProcessBackgrounded(true); | 
|  212   process.SetProcessBackgrounded(false); |  197   process.SetProcessBackgrounded(false); | 
|  213 #endif |  198 #endif | 
|  214   int new_priority = process.GetPriority(); |  199   int new_priority = process.GetPriority(); | 
|  215   EXPECT_EQ(old_priority, new_priority); |  200   EXPECT_EQ(old_priority, new_priority); | 
|  216 } |  201 } | 
|  217  |  202  | 
|  218 #if defined(OS_LINUX) |  | 
|  219 const int kSuccess = 0; |  | 
|  220  |  | 
|  221 MULTIPROCESS_TEST_MAIN(CheckPidProcess) { |  | 
|  222   const pid_t kInitPid = 1; |  | 
|  223   const pid_t pid = syscall(__NR_getpid); |  | 
|  224   CHECK(pid == kInitPid); |  | 
|  225   CHECK(getpid() == pid); |  | 
|  226   return kSuccess; |  | 
|  227 } |  | 
|  228  |  | 
|  229 TEST_F(ProcessTest, CloneFlags) { |  | 
|  230   if (RunningOnValgrind() || !PathExists(FilePath("/proc/self/ns/user")) || |  | 
|  231       !PathExists(FilePath("/proc/self/ns/pid"))) { |  | 
|  232     // User or PID namespaces are not supported. |  | 
|  233     return; |  | 
|  234   } |  | 
|  235  |  | 
|  236   LaunchOptions options; |  | 
|  237   options.clone_flags = CLONE_NEWUSER | CLONE_NEWPID; |  | 
|  238  |  | 
|  239   Process process(SpawnChildWithOptions("CheckPidProcess", options)); |  | 
|  240   ASSERT_TRUE(process.IsValid()); |  | 
|  241  |  | 
|  242   int exit_code = 42; |  | 
|  243   EXPECT_TRUE(process.WaitForExit(&exit_code)); |  | 
|  244   EXPECT_EQ(kSuccess, exit_code); |  | 
|  245 } |  | 
|  246  |  | 
|  247 TEST(ForkWithFlagsTest, UpdatesPidCache) { |  | 
|  248   // The libc clone function, which allows ForkWithFlags to keep the pid cache |  | 
|  249   // up to date, does not work on Valgrind. |  | 
|  250   if (RunningOnValgrind()) { |  | 
|  251     return; |  | 
|  252   } |  | 
|  253  |  | 
|  254   // Warm up the libc pid cache, if there is one. |  | 
|  255   ASSERT_EQ(syscall(__NR_getpid), getpid()); |  | 
|  256  |  | 
|  257   pid_t ctid = 0; |  | 
|  258   const pid_t pid = ForkWithFlags(SIGCHLD | CLONE_CHILD_SETTID, nullptr, &ctid); |  | 
|  259   if (pid == 0) { |  | 
|  260     // In child.  Check both the raw getpid syscall and the libc getpid wrapper |  | 
|  261     // (which may rely on a pid cache). |  | 
|  262     RAW_CHECK(syscall(__NR_getpid) == ctid); |  | 
|  263     RAW_CHECK(getpid() == ctid); |  | 
|  264     _exit(kSuccess); |  | 
|  265   } |  | 
|  266  |  | 
|  267   ASSERT_NE(-1, pid); |  | 
|  268   int status = 42; |  | 
|  269   ASSERT_EQ(pid, HANDLE_EINTR(waitpid(pid, &status, 0))); |  | 
|  270   ASSERT_TRUE(WIFEXITED(status)); |  | 
|  271   EXPECT_EQ(kSuccess, WEXITSTATUS(status)); |  | 
|  272 } |  | 
|  273 #endif |  | 
|  274  |  | 
|  275 #if defined(OS_POSIX) && !defined(OS_ANDROID) |  | 
|  276 const char kPipeValue = '\xcc'; |  | 
|  277  |  | 
|  278 class ReadFromPipeDelegate : public LaunchOptions::PreExecDelegate { |  | 
|  279  public: |  | 
|  280   explicit ReadFromPipeDelegate(int fd) : fd_(fd) {} |  | 
|  281   ~ReadFromPipeDelegate() override {} |  | 
|  282   void RunAsyncSafe() override { |  | 
|  283     char c; |  | 
|  284     RAW_CHECK(HANDLE_EINTR(read(fd_, &c, 1)) == 1); |  | 
|  285     RAW_CHECK(IGNORE_EINTR(close(fd_)) == 0); |  | 
|  286     RAW_CHECK(c == kPipeValue); |  | 
|  287   } |  | 
|  288  |  | 
|  289  private: |  | 
|  290   int fd_; |  | 
|  291   DISALLOW_COPY_AND_ASSIGN(ReadFromPipeDelegate); |  | 
|  292 }; |  | 
|  293  |  | 
|  294 TEST_F(ProcessTest, PreExecHook) { |  | 
|  295   int pipe_fds[2]; |  | 
|  296   ASSERT_EQ(0, pipe(pipe_fds)); |  | 
|  297  |  | 
|  298   ScopedFD read_fd(pipe_fds[0]); |  | 
|  299   ScopedFD write_fd(pipe_fds[1]); |  | 
|  300   base::FileHandleMappingVector fds_to_remap; |  | 
|  301   fds_to_remap.push_back(std::make_pair(read_fd.get(), read_fd.get())); |  | 
|  302  |  | 
|  303   ReadFromPipeDelegate read_from_pipe_delegate(read_fd.get()); |  | 
|  304   LaunchOptions options; |  | 
|  305   options.fds_to_remap = &fds_to_remap; |  | 
|  306   options.pre_exec_delegate = &read_from_pipe_delegate; |  | 
|  307   Process process(SpawnChildWithOptions("SimpleChildProcess", options)); |  | 
|  308   ASSERT_TRUE(process.IsValid()); |  | 
|  309  |  | 
|  310   read_fd.reset(); |  | 
|  311   ASSERT_EQ(1, HANDLE_EINTR(write(write_fd.get(), &kPipeValue, 1))); |  | 
|  312  |  | 
|  313   int exit_code = 42; |  | 
|  314   EXPECT_TRUE(process.WaitForExit(&exit_code)); |  | 
|  315   EXPECT_EQ(0, exit_code); |  | 
|  316 } |  | 
|  317 #endif  // defined(OS_POSIX) && !defined(OS_ANDROID) |  | 
|  318  |  | 
|  319 }  // namespace base |  203 }  // namespace base | 
| OLD | NEW |