Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(422)

Side by Side Diff: base/process_util_posix.cc

Issue 100127: POSIX: Add code for shuffling file descriptors. (Closed)
Patch Set: ... Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/process_util_linux.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « base/process_util_linux.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698