OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 <dirent.h> | 5 #include <dirent.h> |
6 #include <errno.h> | 6 #include <errno.h> |
7 #include <fcntl.h> | 7 #include <fcntl.h> |
8 #include <signal.h> | 8 #include <signal.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include <sys/resource.h> | 10 #include <sys/resource.h> |
11 #include <sys/time.h> | 11 #include <sys/time.h> |
12 #include <sys/types.h> | 12 #include <sys/types.h> |
13 #include <sys/wait.h> | 13 #include <sys/wait.h> |
14 #include <unistd.h> | 14 #include <unistd.h> |
15 | 15 |
16 #include <limits> | 16 #include <limits> |
| 17 #include <set> |
17 | 18 |
18 #include "base/basictypes.h" | 19 #include "base/basictypes.h" |
19 #include "base/logging.h" | 20 #include "base/logging.h" |
20 #include "base/platform_thread.h" | 21 #include "base/platform_thread.h" |
21 #include "base/process_util.h" | 22 #include "base/process_util.h" |
22 #include "base/scoped_ptr.h" | 23 #include "base/scoped_ptr.h" |
23 #include "base/sys_info.h" | 24 #include "base/sys_info.h" |
24 #include "base/time.h" | 25 #include "base/time.h" |
25 #include "base/waitable_event.h" | 26 #include "base/waitable_event.h" |
26 | 27 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 class ScopedDIRClose { | 83 class ScopedDIRClose { |
83 public: | 84 public: |
84 inline void operator()(DIR* x) const { | 85 inline void operator()(DIR* x) const { |
85 if (x) { | 86 if (x) { |
86 closedir(x); | 87 closedir(x); |
87 } | 88 } |
88 } | 89 } |
89 }; | 90 }; |
90 typedef scoped_ptr_malloc<DIR, ScopedDIRClose> ScopedDIR; | 91 typedef scoped_ptr_malloc<DIR, ScopedDIRClose> ScopedDIR; |
91 | 92 |
| 93 void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) { |
| 94 std::set<int> saved_fds; |
| 95 |
| 96 // Don't close stdin, stdout and stderr |
| 97 saved_fds.insert(STDIN_FILENO); |
| 98 saved_fds.insert(STDOUT_FILENO); |
| 99 saved_fds.insert(STDERR_FILENO); |
| 100 |
| 101 for (base::InjectiveMultimap::const_iterator |
| 102 i = saved_mapping.begin(); i != saved_mapping.end(); ++i) { |
| 103 saved_fds.insert(i->dest); |
| 104 } |
| 105 |
| 106 #if defined(OS_LINUX) |
| 107 static const char fd_dir[] = "/proc/self/fd"; |
| 108 #elif defined(OS_MACOSX) |
| 109 static const char fd_dir[] = "/dev/fd"; |
| 110 #endif |
| 111 |
| 112 ScopedDIR dir_closer(opendir(fd_dir)); |
| 113 DIR *dir = dir_closer.get(); |
| 114 if (NULL == dir) { |
| 115 DLOG(ERROR) << "Unable to open " << fd_dir; |
| 116 return; |
| 117 } |
| 118 |
| 119 struct dirent *ent; |
| 120 while ((ent = readdir(dir))) { |
| 121 // Skip . and .. entries. |
| 122 if (ent->d_name[0] == '.') |
| 123 continue; |
| 124 |
| 125 char *endptr; |
| 126 errno = 0; |
| 127 const long int fd = strtol(ent->d_name, &endptr, 10); |
| 128 if (ent->d_name[0] == 0 || *endptr || fd < 0 || fd >= INT_MAX || errno) |
| 129 continue; |
| 130 if (saved_fds.find(fd) != saved_fds.end()) |
| 131 continue; |
| 132 |
| 133 int result; |
| 134 do { |
| 135 result = close(fd); |
| 136 } while (result == -1 && errno == EINTR); |
| 137 } |
| 138 } |
| 139 |
92 // Sets all file descriptors to close on exec except for stdin, stdout | 140 // Sets all file descriptors to close on exec except for stdin, stdout |
93 // and stderr. | 141 // and stderr. |
| 142 // TODO(agl): Remove this function. It's fundamentally broken for multithreaded |
| 143 // apps. |
94 void SetAllFDsToCloseOnExec() { | 144 void SetAllFDsToCloseOnExec() { |
95 #if defined(OS_LINUX) | 145 #if defined(OS_LINUX) |
96 const char fd_dir[] = "/proc/self/fd"; | 146 const char fd_dir[] = "/proc/self/fd"; |
97 #elif defined(OS_MACOSX) | 147 #elif defined(OS_MACOSX) |
98 const char fd_dir[] = "/dev/fd"; | 148 const char fd_dir[] = "/dev/fd"; |
99 #endif | 149 #endif |
100 ScopedDIR dir_closer(opendir(fd_dir)); | 150 ScopedDIR dir_closer(opendir(fd_dir)); |
101 DIR *dir = dir_closer.get(); | 151 DIR *dir = dir_closer.get(); |
102 if (NULL == dir) { | 152 if (NULL == dir) { |
103 DLOG(ERROR) << "Unable to open " << fd_dir; | 153 DLOG(ERROR) << "Unable to open " << fd_dir; |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 case -1: // error | 391 case -1: // error |
342 close(pipe_fd[0]); | 392 close(pipe_fd[0]); |
343 close(pipe_fd[1]); | 393 close(pipe_fd[1]); |
344 return false; | 394 return false; |
345 case 0: // child | 395 case 0: // child |
346 { | 396 { |
347 int dev_null = open("/dev/null", O_WRONLY); | 397 int dev_null = open("/dev/null", O_WRONLY); |
348 if (dev_null < 0) | 398 if (dev_null < 0) |
349 exit(127); | 399 exit(127); |
350 | 400 |
351 int rv; | 401 InjectiveMultimap fd_shuffle; |
352 do { | 402 fd_shuffle.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true)); |
353 rv = dup2(pipe_fd[1], STDOUT_FILENO); | 403 fd_shuffle.push_back(InjectionArc(dev_null, STDERR_FILENO, true)); |
354 } while (rv == -1 && errno == EINTR); | 404 fd_shuffle.push_back(InjectionArc(dev_null, STDIN_FILENO, true)); |
355 do { | 405 |
356 rv = dup2(dev_null, STDERR_FILENO); | 406 if (!ShuffleFileDescriptors(fd_shuffle)) |
357 } while (rv == -1 && errno == EINTR); | 407 exit(127); |
358 if (pipe_fd[0] != STDOUT_FILENO && pipe_fd[0] != STDERR_FILENO) | 408 |
359 close(pipe_fd[0]); | 409 CloseSuperfluousFds(fd_shuffle); |
360 if (pipe_fd[1] != STDOUT_FILENO && pipe_fd[1] != STDERR_FILENO) | |
361 close(pipe_fd[1]); | |
362 if (dev_null != STDOUT_FILENO && dev_null != STDERR_FILENO) | |
363 close(dev_null); | |
364 | 410 |
365 const std::vector<std::string> argv = cl.argv(); | 411 const std::vector<std::string> argv = cl.argv(); |
366 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]); | 412 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]); |
367 for (size_t i = 0; i < argv.size(); i++) | 413 for (size_t i = 0; i < argv.size(); i++) |
368 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); | 414 argv_cstr[i] = const_cast<char*>(argv[i].c_str()); |
369 argv_cstr[argv.size()] = NULL; | 415 argv_cstr[argv.size()] = NULL; |
370 execvp(argv_cstr[0], argv_cstr.get()); | 416 execvp(argv_cstr[0], argv_cstr.get()); |
371 exit(127); | 417 exit(127); |
372 } | 418 } |
373 default: // parent | 419 default: // parent |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 const ProcessFilter* filter) { | 500 const ProcessFilter* filter) { |
455 bool exited_cleanly = | 501 bool exited_cleanly = |
456 WaitForProcessesToExit(executable_name, wait_milliseconds, | 502 WaitForProcessesToExit(executable_name, wait_milliseconds, |
457 filter); | 503 filter); |
458 if (!exited_cleanly) | 504 if (!exited_cleanly) |
459 KillProcesses(executable_name, exit_code, filter); | 505 KillProcesses(executable_name, exit_code, filter); |
460 return exited_cleanly; | 506 return exited_cleanly; |
461 } | 507 } |
462 | 508 |
463 } // namespace base | 509 } // namespace base |
OLD | NEW |