Chromium Code Reviews| Index: base/process/process_util_unittest.cc |
| diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc |
| index 20623a60e18a6cfba0bbe86721ceb718cde91d84..9a81ae684242988d0b2b7f201b302249f552b036 100644 |
| --- a/base/process/process_util_unittest.cc |
| +++ b/base/process/process_util_unittest.cc |
| @@ -50,6 +50,7 @@ |
| #if defined(OS_MACOSX) |
| #include <mach/vm_param.h> |
| #include <malloc/malloc.h> |
| +#include "base/mac/mac_util.h" |
| #endif |
| using base::FilePath; |
| @@ -469,6 +470,76 @@ int GetMaxFilesOpenInProcess() { |
| const int kChildPipe = 20; // FD # for write end of pipe in child process. |
| +#if defined(OS_MACOSX) |
| + |
| +// <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/sys/guarded.h> |
| +#if !defined(_GUARDID_T) |
| +#define _GUARDID_T |
| +typedef __uint64_t guardid_t; |
| +#endif // _GUARDID_T |
| + |
| +// From .../MacOSX10.9.sdk/usr/include/sys/syscall.h |
| +#if !defined(SYS_change_fdguard_np) |
| +#define SYS_change_fdguard_np 444 |
| +#endif |
| + |
| +// <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/sys/guarded.h> |
| +#if !defined(GUARD_DUP) |
| +#define GUARD_DUP (1u << 1) |
| +#endif |
| + |
| +// <http://opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/kern/kern_guarded.c?txt> |
| +// |
| +// Atomically replaces |guard|/|guardflags| with |nguard|/|nguardflags| on |fd|. |
| +int my_change_fdguard_np(int fd, |
| + const guardid_t *guard, u_int guardflags, |
| + const guardid_t *nguard, u_int nguardflags, |
| + int *fdflagsp) { |
| + // TODO(shess): Citation needed. |
| + // TODO(shess): What about older kernels? |
| + // TODO(shess): Insanity much? |
| + return syscall(SYS_change_fdguard_np, fd, guard, guardflags, |
| + nguard, nguardflags, fdflagsp); |
| +} |
| + |
| +// Attempt to set a file-descriptor guard on |fd|. In case of success, remove |
| +// it and return |true| to indicate that it is now unguarded. Returning |false| |
| +// means either that |fd| is guarded, or more likely EBADF. |
| +// |
| +// Starting with 10.9, libdispatch began setting GUARD_DUP on a file descriptor. |
| +// Unfortunately, it is spun up as part of +[NSApplication initialize], which is |
| +// not really something that Chromium can avoid using on OSX. See |
| +// <http://crbug.com/338157>. This function allows querying whether the file |
| +// descriptor is guarded before attempting to close it. |
| +bool is_fd_unguarded(int fd) { |
|
Mark Mentovai
2014/07/25 13:23:43
Naming.
Scott Hess - ex-Googler
2014/07/28 19:58:03
Done.
I also changed my_guard_fdguard_np -> guard
|
| + // The syscall is first provided in 10.9/Mavericks. |
| + if (!base::mac::IsOSMavericksOrLater()) |
| + return true; |
| + |
| + // Saves the original flags to reset later. |
| + int original_fdflags = 0; |
|
Mark Mentovai
2014/07/25 13:23:43
The kernel calls these unsigned ints, might as wel
Scott Hess - ex-Googler
2014/07/28 19:58:03
The guard flags are unsigned, but the fdflags are
|
| + |
| + // This can be any value at all, it just has to match up between the two |
| + // calls. |
| + const guardid_t kGuard = 15; |
| + |
| + // Attempt to change the guard. This can fail with EBADF if the file |
| + // descriptor is bad, or EINVAL if the fd already has a guard set. |
| + int ret = HANDLE_EINTR(my_change_fdguard_np( |
|
Mark Mentovai
2014/07/25 13:23:43
I don’t think HANDLE_EINTR is really needed around
Scott Hess - ex-Googler
2014/07/28 19:58:03
Done.
|
| + fd, NULL, 0, &kGuard, GUARD_DUP, &original_fdflags)); |
| + if (ret == -1) |
| + return false; |
| + |
| + // Remove the guard. It should not be possible to fail in removing the guard |
| + // just added. |
| + ret = HANDLE_EINTR(my_change_fdguard_np( |
| + fd, &kGuard, GUARD_DUP, NULL, 0, &original_fdflags)); |
| + DPCHECK(ret == 0); |
| + |
| + return true; |
| +} |
| +#endif // OS_MACOSX |
| + |
| } // namespace |
| MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess) { |
| @@ -478,6 +549,12 @@ MULTIPROCESS_TEST_MAIN(ProcessUtilsLeakFDChildProcess) { |
| int write_pipe = kChildPipe; |
| int max_files = GetMaxFilesOpenInProcess(); |
| for (int i = STDERR_FILENO + 1; i < max_files; i++) { |
| +#if defined(OS_MACOSX) |
| + // Ignore guarded file descriptors. |
| + if (!is_fd_unguarded(i)) |
|
Mark Mentovai
2014/07/25 13:23:43
This is kind of a double negative, and considering
Scott Hess - ex-Googler
2014/07/28 19:58:03
Changed to CanGuardFd(). The reason for this sens
|
| + continue; |
| +#endif |
| + |
| if (i != kChildPipe) { |
| int fd; |
| if ((fd = HANDLE_EINTR(dup(i))) != -1) { |