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 |