diff options
author | jeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-17 22:41:50 +0000 |
---|---|---|
committer | jeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-17 22:41:50 +0000 |
commit | fa3097a6a5ec6c6e7c092a6339c283dc34d42ca7 (patch) | |
tree | 7fc997f0a3cb9ce2aca5411e43c1987e6618b7d1 /base/process_util_unittest.cc | |
parent | 6f666448fe72b6f98a241cb9d83a2a15aa4ff24e (diff) | |
download | chromium_src-fa3097a6a5ec6c6e7c092a6339c283dc34d42ca7.zip chromium_src-fa3097a6a5ec6c6e7c092a6339c283dc34d42ca7.tar.gz chromium_src-fa3097a6a5ec6c6e7c092a6339c283dc34d42ca7.tar.bz2 |
* On POSIX, make sure we don't leak FDs when launching child Processes.
* Add a facility to LaunchProcess() to remap a given FD into a child process.
This change is needed for 2 reasons:
1)We want to use a socketpair() for IPC, the child process needs a known FD # for it's side of the socket.
2)The OS X Sandbox doesn't close FDs.
Review URL: http://codereview.chromium.org/14497
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@7175 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/process_util_unittest.cc')
-rw-r--r-- | base/process_util_unittest.cc | 77 |
1 files changed, 75 insertions, 2 deletions
diff --git a/base/process_util_unittest.cc b/base/process_util_unittest.cc index 7e8b9a2..67c9500 100644 --- a/base/process_util_unittest.cc +++ b/base/process_util_unittest.cc @@ -9,10 +9,15 @@ #include "base/process_util.h" #include "testing/gtest/include/gtest/gtest.h" +#if defined(OS_LINUX) +#include <dlfcn.h> +#endif +#if defined(OS_POSIX) +#include <fcntl.h> +#include <sys/socket.h> +#endif #if defined(OS_WIN) #include <windows.h> -#elif defined(OS_LINUX) -#include <dlfcn.h> #endif namespace base { @@ -137,4 +142,72 @@ TEST_F(ProcessUtilTest, CalcFreeMemory) { } #endif // defined(OS_WIN) +#if defined(OS_POSIX) +const int kChildPipe = 20; // FD # for write end of pipe in child process. +MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess) { + // This child process counts the number of open FDs, it then writes that + // number out to a pipe connected to the parent. + int num_open_files = 0; + int write_pipe = kChildPipe; + int max_files = GetMaxFilesOpenInProcess(); + for (int i = STDERR_FILENO + 1; i < max_files; i++) { + if (i != kChildPipe) { + if (close(i) != -1) { + LOG(WARNING) << "Leaked FD " << i; + num_open_files += 1; + } + } + } + +#if defined(OS_LINUX) + // On Linux, '/etc/localtime' is opened before the test's main() enters. + const int expected_num_open_fds = 1; + num_open_files -= expected_num_open_fds; +#endif // defined(OS_LINUX) + + write(write_pipe, &num_open_files, sizeof(num_open_files)); + close(write_pipe); + + return 0; +} + +TEST_F(ProcessUtilTest, FDRemapping) { + // Open some files to check they don't get leaked to the child process. + int fds[2]; + pipe(fds); + int pipe_read_fd = fds[0]; + int pipe_write_fd = fds[1]; + + // open some dummy fds to make sure they don't propogate over to the + // child process. + int dev_null = open("/dev/null", O_RDONLY); + int sockets[2]; + socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); + + file_handle_mapping_vector fd_mapping_vec; + fd_mapping_vec.push_back(std::pair<int,int>(pipe_write_fd, kChildPipe)); + ProcessHandle handle = this->SpawnChild(L"ProcessUtilsLeakFDChildProcess", + fd_mapping_vec, + false); + ASSERT_NE(static_cast<ProcessHandle>(NULL), handle); + close(pipe_write_fd); + + // Read number of open files in client process from pipe; + int num_open_files = -1; + ssize_t bytes_read = read(pipe_read_fd, &num_open_files, + sizeof(num_open_files)); + ASSERT_EQ(bytes_read, static_cast<ssize_t>(sizeof(num_open_files))); + + // Make sure 0 fds are leaked to the client. + ASSERT_EQ(0, num_open_files); + + EXPECT_TRUE(WaitForSingleProcess(handle, 1000)); + close(fds[0]); + close(sockets[0]); + close(sockets[1]); + close(dev_null); +} + +#endif // defined(OS_POSIX) + } // namespace base |