| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 #define _CRT_SECURE_NO_WARNINGS | 5 #define _CRT_SECURE_NO_WARNINGS |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/eintr_wrapper.h" | 8 #include "base/eintr_wrapper.h" |
| 9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
| 10 #include "base/multiprocess_test.h" | 10 #include "base/multiprocess_test.h" |
| 11 #include "base/path_service.h" | 11 #include "base/path_service.h" |
| 12 #include "base/platform_thread.h" | 12 #include "base/platform_thread.h" |
| 13 #include "base/process_util.h" | 13 #include "base/process_util.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 | 15 |
| 16 #if defined(OS_LINUX) | 16 #if defined(OS_LINUX) |
| 17 #include <dlfcn.h> | 17 #include <dlfcn.h> |
| 18 #endif | 18 #endif |
| 19 #if defined(OS_POSIX) | 19 #if defined(OS_POSIX) |
| 20 #include <fcntl.h> | 20 #include <fcntl.h> |
| 21 #include <sys/socket.h> | 21 #include <sys/socket.h> |
| 22 #endif | 22 #endif |
| 23 #if defined(OS_WIN) | 23 #if defined(OS_WIN) |
| 24 #include <windows.h> | 24 #include <windows.h> |
| 25 #endif | 25 #endif |
| 26 | 26 |
| 27 namespace base { | 27 namespace base { |
| 28 | 28 |
| 29 class ProcessUtilTest : public MultiProcessTest { | 29 class ProcessUtilTest : public MultiProcessTest { |
| 30 #if defined(OS_POSIX) |
| 31 public: |
| 32 // Spawn a child process that counts how many file descriptors are open. |
| 33 int CountOpenFDsInChild(); |
| 34 #endif |
| 30 }; | 35 }; |
| 31 | 36 |
| 32 MULTIPROCESS_TEST_MAIN(SimpleChildProcess) { | 37 MULTIPROCESS_TEST_MAIN(SimpleChildProcess) { |
| 33 return 0; | 38 return 0; |
| 34 } | 39 } |
| 35 | 40 |
| 36 TEST_F(ProcessUtilTest, SpawnChild) { | 41 TEST_F(ProcessUtilTest, SpawnChild) { |
| 37 ProcessHandle handle = this->SpawnChild(L"SimpleChildProcess"); | 42 ProcessHandle handle = this->SpawnChild(L"SimpleChildProcess"); |
| 38 | 43 |
| 39 ASSERT_NE(static_cast<ProcessHandle>(NULL), handle); | 44 ASSERT_NE(static_cast<ProcessHandle>(NULL), handle); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 int max_files = GetMaxFilesOpenInProcess(); | 198 int max_files = GetMaxFilesOpenInProcess(); |
| 194 for (int i = STDERR_FILENO + 1; i < max_files; i++) { | 199 for (int i = STDERR_FILENO + 1; i < max_files; i++) { |
| 195 if (i != kChildPipe) { | 200 if (i != kChildPipe) { |
| 196 if (HANDLE_EINTR(close(i)) != -1) { | 201 if (HANDLE_EINTR(close(i)) != -1) { |
| 197 LOG(WARNING) << "Leaked FD " << i; | 202 LOG(WARNING) << "Leaked FD " << i; |
| 198 num_open_files += 1; | 203 num_open_files += 1; |
| 199 } | 204 } |
| 200 } | 205 } |
| 201 } | 206 } |
| 202 | 207 |
| 203 // InitLogging always opens a file at startup. | |
| 204 int expected_num_open_fds = 1; | |
| 205 #if defined(OS_LINUX) | |
| 206 // On Linux, '/etc/localtime' is opened before the test's main() enters. | |
| 207 expected_num_open_fds += 1; | |
| 208 #endif // defined(OS_LINUX) | |
| 209 num_open_files -= expected_num_open_fds; | |
| 210 | |
| 211 int written = HANDLE_EINTR(write(write_pipe, &num_open_files, | 208 int written = HANDLE_EINTR(write(write_pipe, &num_open_files, |
| 212 sizeof(num_open_files))); | 209 sizeof(num_open_files))); |
| 213 DCHECK_EQ(static_cast<size_t>(written), sizeof(num_open_files)); | 210 DCHECK_EQ(static_cast<size_t>(written), sizeof(num_open_files)); |
| 214 HANDLE_EINTR(close(write_pipe)); | 211 HANDLE_EINTR(close(write_pipe)); |
| 215 | 212 |
| 216 return 0; | 213 return 0; |
| 217 } | 214 } |
| 218 | 215 |
| 219 TEST_F(ProcessUtilTest, FDRemapping) { | 216 int ProcessUtilTest::CountOpenFDsInChild() { |
| 220 // Open some files to check they don't get leaked to the child process. | |
| 221 int fds[2]; | 217 int fds[2]; |
| 222 if (pipe(fds) < 0) | 218 if (pipe(fds) < 0) |
| 223 NOTREACHED(); | 219 NOTREACHED(); |
| 224 int pipe_read_fd = fds[0]; | 220 |
| 225 int pipe_write_fd = fds[1]; | 221 file_handle_mapping_vector fd_mapping_vec; |
| 222 fd_mapping_vec.push_back(std::pair<int,int>(fds[1], kChildPipe)); |
| 223 ProcessHandle handle = this->SpawnChild(L"ProcessUtilsLeakFDChildProcess", |
| 224 fd_mapping_vec, |
| 225 false); |
| 226 CHECK(static_cast<ProcessHandle>(NULL) != handle); |
| 227 HANDLE_EINTR(close(fds[1])); |
| 228 |
| 229 // Read number of open files in client process from pipe; |
| 230 int num_open_files = -1; |
| 231 ssize_t bytes_read = |
| 232 HANDLE_EINTR(read(fds[0], &num_open_files, sizeof(num_open_files))); |
| 233 CHECK(bytes_read == static_cast<ssize_t>(sizeof(num_open_files))); |
| 234 |
| 235 CHECK(WaitForSingleProcess(handle, 1000)); |
| 236 base::CloseProcessHandle(handle); |
| 237 HANDLE_EINTR(close(fds[0])); |
| 238 |
| 239 return num_open_files; |
| 240 } |
| 241 |
| 242 TEST_F(ProcessUtilTest, FDRemapping) { |
| 243 int fds_before = CountOpenFDsInChild(); |
| 226 | 244 |
| 227 // open some dummy fds to make sure they don't propogate over to the | 245 // open some dummy fds to make sure they don't propogate over to the |
| 228 // child process. | 246 // child process. |
| 229 int dev_null = open("/dev/null", O_RDONLY); | 247 int dev_null = open("/dev/null", O_RDONLY); |
| 230 int sockets[2]; | 248 int sockets[2]; |
| 231 socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); | 249 socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); |
| 232 | 250 |
| 233 file_handle_mapping_vector fd_mapping_vec; | 251 int fds_after = CountOpenFDsInChild(); |
| 234 fd_mapping_vec.push_back(std::pair<int,int>(pipe_write_fd, kChildPipe)); | |
| 235 ProcessHandle handle = this->SpawnChild(L"ProcessUtilsLeakFDChildProcess", | |
| 236 fd_mapping_vec, | |
| 237 false); | |
| 238 ASSERT_NE(static_cast<ProcessHandle>(NULL), handle); | |
| 239 HANDLE_EINTR(close(pipe_write_fd)); | |
| 240 | 252 |
| 241 // Read number of open files in client process from pipe; | 253 ASSERT_EQ(fds_after, fds_before); |
| 242 int num_open_files = -1; | |
| 243 ssize_t bytes_read = | |
| 244 HANDLE_EINTR(read(pipe_read_fd, &num_open_files, sizeof(num_open_files))); | |
| 245 ASSERT_EQ(bytes_read, static_cast<ssize_t>(sizeof(num_open_files))); | |
| 246 | 254 |
| 247 // Make sure 0 fds are leaked to the client. | |
| 248 ASSERT_EQ(0, num_open_files); | |
| 249 | |
| 250 EXPECT_TRUE(WaitForSingleProcess(handle, 1000)); | |
| 251 base::CloseProcessHandle(handle); | |
| 252 HANDLE_EINTR(close(fds[0])); | |
| 253 HANDLE_EINTR(close(sockets[0])); | 255 HANDLE_EINTR(close(sockets[0])); |
| 254 HANDLE_EINTR(close(sockets[1])); | 256 HANDLE_EINTR(close(sockets[1])); |
| 255 HANDLE_EINTR(close(dev_null)); | 257 HANDLE_EINTR(close(dev_null)); |
| 256 } | 258 } |
| 257 | 259 |
| 258 TEST_F(ProcessUtilTest, GetAppOutput) { | 260 TEST_F(ProcessUtilTest, GetAppOutput) { |
| 259 std::string output; | 261 std::string output; |
| 260 EXPECT_TRUE(GetAppOutput(CommandLine(L"true"), &output)); | 262 EXPECT_TRUE(GetAppOutput(CommandLine(L"true"), &output)); |
| 261 EXPECT_STREQ("", output.c_str()); | 263 EXPECT_STREQ("", output.c_str()); |
| 262 | 264 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 273 #if defined(OS_LINUX) | 275 #if defined(OS_LINUX) |
| 274 TEST_F(ProcessUtilTest, GetParentProcessId) { | 276 TEST_F(ProcessUtilTest, GetParentProcessId) { |
| 275 base::ProcessId ppid = GetParentProcessId(GetCurrentProcId()); | 277 base::ProcessId ppid = GetParentProcessId(GetCurrentProcId()); |
| 276 EXPECT_EQ(ppid, getppid()); | 278 EXPECT_EQ(ppid, getppid()); |
| 277 } | 279 } |
| 278 #endif | 280 #endif |
| 279 | 281 |
| 280 #endif // defined(OS_POSIX) | 282 #endif // defined(OS_POSIX) |
| 281 | 283 |
| 282 } // namespace base | 284 } // namespace base |
| OLD | NEW |